Initial commit

This commit is contained in:
2025-08-05 17:01:29 +02:00
commit 20c74361c9
11 changed files with 294 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,35 @@
{
"images" : [
{
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "tinted"
}
],
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

76
QuizApp/ContentView.swift Normal file
View File

@@ -0,0 +1,76 @@
//
// ContentView.swift
// QuizApp
//
// Created by Paul Nowotka on 02.08.25.
//
import SwiftUI
struct ContentView: View {
@ObservedObject var viewModel = ViewModel()
@State private var selectedAnswerIndex: Int? = nil
@State private var isAnswered = false
var body: some View {
VStack {
if let frage = viewModel.topics.first {
Text(frage.question)
.font(.title)
.multilineTextAlignment(.center)
.padding()
ForEach(frage.answers.indices, id: \.self) { index in
Button(action: {
selectedAnswerIndex = index
isAnswered = true
print("Selected:", index)
print("Correct:", frage.correctAnswer)
}) {
Text(frage.answers[index])
.padding()
.frame(maxWidth: 300)
.background(buttonColor(for: index, correctIndex: frage.correctAnswer))
.foregroundColor(.white)
.cornerRadius(10)
}
.disabled(isAnswered)
}
VStack {
if isAnswered {
Text(selectedAnswerIndex == frage.correctAnswer ? "✅ Richtig!" : "❌ Falsch")
.font(.headline)
.foregroundColor(selectedAnswerIndex == frage.correctAnswer ? .green : .red)
.padding()
}
if isAnswered {
Button("Nächste Frage") {
selectedAnswerIndex = nil
isAnswered = false
}
}
}
.frame(height: 80)
} else {
Text("Fragen werden geladen...")
}
}
}
private func buttonColor(for index: Int, correctIndex: Int) -> Color {
guard isAnswered else { return .blue }
if index == correctIndex {
return .green
} else if index == selectedAnswerIndex {
return .red
} else {
return .gray
}
}
}
#Preview {
ContentView()
}

17
QuizApp/QuizAppApp.swift Normal file
View File

@@ -0,0 +1,17 @@
//
// QuizAppApp.swift
// QuizApp
//
// Created by Paul Nowotka on 02.08.25.
//
import SwiftUI
@main
struct QuizAppApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}

16
QuizApp/Topic.swift Normal file
View File

@@ -0,0 +1,16 @@
//
// Topic.swift
// QuizApp
//
// Created by Paul Nowotka on 03.08.25.
//
import Foundation
struct Topic: Decodable, Hashable {
let question: String
let answers: [String]
let correctAnswer: Int
}

30
QuizApp/ViewModel.swift Normal file
View File

@@ -0,0 +1,30 @@
//
// ViewModel.swift
// QuizApp
//
// Created by Paul Nowotka on 03.08.25.
//
import Foundation
class ViewModel: ObservableObject {
let topics: [Topic]
@Published var currentQuestionIndex: Int = 0
init() {
guard let url = Bundle.main.url(forResource: "data", withExtension: "json") else {
topics = []
return
}
do {
let data = try Data(contentsOf: url)
topics = try JSONDecoder().decode([Topic].self, from: data)
} catch {
print("Fehler beim Laden des Inhalts: \(error)")
topics = []
}
}
}

12
QuizApp/data.json Normal file
View File

@@ -0,0 +1,12 @@
[
{
"question": "Was ist die Hauptstadt von Frankreich?",
"answers": ["Rom", "Berlin", "Paris"],
"correctAnswer": 2
},
{
"question": "Was ist die Hauptstadt von Deutschland?",
"answers": ["Rom", "Berlin", "Paris"],
"correctAnswer": 1
}
]

View File

@@ -0,0 +1,17 @@
//
// QuizAppTests.swift
// QuizAppTests
//
// Created by Paul Nowotka on 02.08.25.
//
import Testing
@testable import QuizApp
struct QuizAppTests {
@Test func example() async throws {
// Write your test here and use APIs like `#expect(...)` to check expected conditions.
}
}

View File

@@ -0,0 +1,41 @@
//
// QuizAppUITests.swift
// QuizAppUITests
//
// Created by Paul Nowotka on 02.08.25.
//
import XCTest
final class QuizAppUITests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
// In UI tests it is usually best to stop immediately when a failure occurs.
continueAfterFailure = false
// In UI tests its important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
@MainActor
func testExample() throws {
// UI tests must launch the application that they test.
let app = XCUIApplication()
app.launch()
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
@MainActor
func testLaunchPerformance() throws {
// This measures how long it takes to launch your application.
measure(metrics: [XCTApplicationLaunchMetric()]) {
XCUIApplication().launch()
}
}
}

View File

@@ -0,0 +1,33 @@
//
// QuizAppUITestsLaunchTests.swift
// QuizAppUITests
//
// Created by Paul Nowotka on 02.08.25.
//
import XCTest
final class QuizAppUITestsLaunchTests: XCTestCase {
override class var runsForEachTargetApplicationUIConfiguration: Bool {
true
}
override func setUpWithError() throws {
continueAfterFailure = false
}
@MainActor
func testLaunch() throws {
let app = XCUIApplication()
app.launch()
// Insert steps here to perform after app launch but before taking a screenshot,
// such as logging into a test account or navigating somewhere in the app
let attachment = XCTAttachment(screenshot: app.screenshot())
attachment.name = "Launch Screen"
attachment.lifetime = .keepAlways
add(attachment)
}
}