WebAppView + viel kaputtes

This commit is contained in:
Ingo Rohlf 2025-10-23 13:45:41 +02:00
parent cd16b94917
commit 42b110637a
13 changed files with 553 additions and 115 deletions

View file

@ -14,7 +14,7 @@ struct TheSwiftWeek: App {
// ContentView() // ContentView()
UnicycleView() ContentView()
}.modelContainer(for: Unicycle.self) }.modelContainer(for: Unicycle.self)

View file

@ -8,16 +8,21 @@ struct BikeView: TabContent {
static var image = "bicycle" static var image = "bicycle"
var bike = Bike(name: "Fahrrad", price: 11.31, color: Color.cyan) var bike = Bike(name: "Mein Fahrrad ", price: 11.31, color: Color.cyan)
var body: some View { var body: some View {
VStack{ HStack {
Label(bike.name, systemImage: "bicycle") Label(bike.name, systemImage: "bicycle")
.foregroundStyle(.white) .foregroundStyle(.white)
.padding(5) .padding(5)
.background(bike.color) .background(bike.color)
// .frame(width: 200)
// Spacer()
Text(bike.price, format: .currency( code: "EUR"))
} }
} }
} }

View file

@ -1,56 +1,45 @@
//
// ListView.swift
// TheSwiftWeek
//
// Created by Ingo Rohlf on 21.10.25.
//
import SwiftUI import SwiftUI
//import Playgrounds struct ListView: TabContent {
import Foundation
struct ListView: TabContent{
static var title = "List" static var title = "List"
static var image = "list.bullet" static var image = "list.bullet"
static var id = UUID()
@State var bikes = Bike.all @State var bikes = Bike.all
@FocusState var focusedField: UUID? // 1
var body: some View { var body: some View {
List { List {
Text(bikes[0].name) Section {
Text(bikes[1].name) ForEach($bikes) { $bike in
Text(bikes[2].name) // HStack {
} // TextField("New Bike", text: $bike.name)
List(bikes, id: \.name){ bike in // .focused($focusedField, equals: bike.id)
// .textFieldStyle(.roundedBorder)
// Spacer()
// Text("\(bike.price, specifier: "%.2f")")
// ColorPicker("", selection: $bike.color)
// }
HStack { HStack {
BikeView(bike: bike)
Color(bike.color)
//Circle().fill(style: bike.color)
Text(String(bike.name))
Spacer() Spacer()
} ColorPicker("", selection: $bike.color)
}
List(bikes, id: \.name){
Text(String($0.price))
}
// Weil Vehicle jetzt Identifiable implementiert, geht es ohne id: \.name
List(bikes){
Text(String($0.name))
} }
}
.onDelete { bikes.remove(atOffsets: $0) }
} footer: {
Button("Add a new Bike") {
let bike = Bike(name: "", color: .white)
bikes.append(bike)
// focusedField = bike.id
}
.frame(maxWidth: .infinity, alignment: .center)
}
}
} }
} }
//#Playground {
// var students = ["Bill", "Linus"]
// let size = [1.65, 1.79]
//}
#Preview { #Preview {
ListView() ListView()
} }

View file

@ -1,16 +1,19 @@
{ {
"sourceLanguage" : "en", "sourceLanguage" : "en",
"strings" : { "strings" : {
"" : {
},
"%lld" : { "%lld" : {
"comment" : "A text element displaying a number. The content of the text element is the integer passed to this view's initializer.", "comment" : "A text element displaying a number. The content of the text element is the integer passed to this view's initializer.",
"isCommentAutoGenerated" : true "isCommentAutoGenerated" : true
}, },
"Add Bike" : { "Add a new Bike" : {
"comment" : "A button that adds a new bike to the list of bikes.", "comment" : "A button that allows adding a new bike to the list.",
"isCommentAutoGenerated" : true "isCommentAutoGenerated" : true
}, },
"Add unicycle" : { "Add Bike" : {
"comment" : "A button that adds a new unicycle to the list.", "comment" : "A button that adds a new bike to the list of bikes.",
"isCommentAutoGenerated" : true "isCommentAutoGenerated" : true
}, },
"Bikes" : { "Bikes" : {
@ -33,10 +36,6 @@
} }
} }
}, },
"Einrad von %@" : {
"comment" : "A list item displaying the creation date of a unicycle.",
"isCommentAutoGenerated" : true
},
"Enter Emoji" : { "Enter Emoji" : {
"comment" : "A label for an text field where the user can enter an emoji.", "comment" : "A label for an text field where the user can enter an emoji.",
"isCommentAutoGenerated" : true "isCommentAutoGenerated" : true
@ -45,10 +44,6 @@
"comment" : "A word that is displayed when the number is a multiple of 3.", "comment" : "A word that is displayed when the number is a multiple of 3.",
"isCommentAutoGenerated" : true "isCommentAutoGenerated" : true
}, },
"Hello, World!" : {
"comment" : "A greeting message displayed in the preview.",
"isCommentAutoGenerated" : true
},
"My Vehicle" : { "My Vehicle" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {
@ -66,6 +61,10 @@
} }
} }
}, },
"please update to iOS 26.0 or later" : {
"comment" : "A message to inform the user that they need to update their iOS version to 26.0 or later to use this feature.",
"isCommentAutoGenerated" : true
},
"Show Alert" : { "Show Alert" : {
"comment" : "A button that triggers an alert when pressed.", "comment" : "A button that triggers an alert when pressed.",
"isCommentAutoGenerated" : true "isCommentAutoGenerated" : true
@ -124,6 +123,10 @@
} }
} }
} }
},
"WebView für iOS 26+" : {
"comment" : "A title for the view that displays a web view.",
"isCommentAutoGenerated" : true
} }
}, },
"version" : "1.1" "version" : "1.1"

View file

@ -48,11 +48,23 @@ struct Train: @MainActor Vehicle, CustomStringConvertible , CustomLocalizedStrin
self.content = content() self.content = content()
} }
} }
enum BikeType: String, Codable, CaseIterable, Identifiable {
var id: String { rawValue }
case unknown
case mountain
case city
case gravel
}
struct Bike: @MainActor Vehicle, CustomStringConvertible { struct Bike: @MainActor Vehicle, CustomStringConvertible {
var name: String var name: String
var price: Double var price: Double = Double(Int.random(in: 3...8)*50) - 0.51
var color: Color var color: Color
var type: BikeType = .unknown
// var description: String { name + " is " + color } // var description: String { name + " is " + color }
var description: String {"\(name) is \(color)" } var description: String {"\(name) is \(color)" }
@ -63,8 +75,8 @@ struct Bike: @MainActor Vehicle, CustomStringConvertible {
print("emptied", Date()) print("emptied", Date())
} }
static var all: [Bike] = [ static var all: [Bike] = [
Bike(name: "Specialized",price: 100000.00, color: .purple ), Bike(name: "Specialized",price: 149.98, color: .purple ),
Bike(name: "Giant",price: 120000.00, color: .red ), Bike(name: "Giant",price: 129.00, color: .red ),
Bike(name: "Cannondale",price: 110000.00, color: .green ) Bike(name: "Cannondale",price: 299.00, color: .green )
] ]
} }

100
NewUnicycleView.swift Normal file
View file

@ -0,0 +1,100 @@
//
//
//import SwiftUI
//import SwiftData
//
//struct NewUnicycleView: View {
// @Environment(\.modelContext) private var modelContext
//
// @State private var isPresented = false
// @State private var sortOrder = SortDescriptor(\Unicycle.name)
// @State private var search = ""
//
// var body: some View {
// NavigationStack {
// UniListView(filter: search, sort: sortOrder)
// .searchable(text: $search)
// .toolbar {
// ToolbarItem(placement: .topBarLeading) {
// EditButton()
// }
// ToolbarItem(placement: .topBarTrailing) {
// HStack {
//
// Button("Add", systemImage: "plus") { isPresented = true }
// picker
// }
// }
// }
// .sheet(isPresented: $isPresented) {
// UniDetailView(uni: Unicycle())
// }
// Button("Save 3") {
// try? modelContext.save()
// }
// }
// }
//
// var picker: some View {
// Menu("Sort", systemImage: "arrow.up.arrow.down") {
// Picker("Sort", selection: $sortOrder) {
// Text("Name 55")
// .tag(SortDescriptor(\Unicycle.name))
// Text("Date")
// .tag(SortDescriptor(\Unicycle.createdAt, order: .reverse))
// Button("Save") {
// try? modelContext.save()
// }
// }
//
// .pickerStyle(.inline)
// }
// }
// struct UniDetailView: View {
// @Bindable var uni: Unicycle
// @State var color: Color
// @Environment(\.modelContext) private var modelContext
//
// init(uni: Unicycle) {
// self.uni = uni
// _color = State(initialValue: Color(red: uni.red, green: uni.green, blue: uni.blue))
// }
//
// var body: some View {
// VStack {
// Text(uni.createdAt.description)
// ColorPicker("Color", selection: Binding(
// get: { color as! CGColor },
// set: {
// color = $0
//// if let comps = $0.rgbComponents() {
//// uni.red = Double(comps.red)
//// uni.green = Double(comps.green)
//// uni.blue = Double(comps.blue)
//// }
// }
// ))
// TextField("Enter name", text: $uni.name)
// .textFieldStyle(.roundedBorder)
// .padding()
// Button("Save 3") {
// try? modelContext.save()
//
//
// }
// }
// .padding()
// .onChange(of: color) {
// if let comps = color.rgbComponents() {
// uni.red = Double(comps.red)
// uni.green = Double(comps.green)
// uni.blue = Double(comps.blue)
// }
// }
// }
// }
//}
//
//#Preview {
// NewUnicycleView()
//}

View file

@ -25,6 +25,9 @@
FBA6FA622EA76AAD00C373EC /* BikeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBA6FA612EA76AAD00C373EC /* BikeView.swift */; }; FBA6FA622EA76AAD00C373EC /* BikeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBA6FA612EA76AAD00C373EC /* BikeView.swift */; };
FBA6FA642EA7715E00C373EC /* Extentions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBA6FA632EA7715000C373EC /* Extentions.swift */; }; FBA6FA642EA7715E00C373EC /* Extentions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBA6FA632EA7715000C373EC /* Extentions.swift */; };
FBA6FA662EA7725A00C373EC /* TrainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBA6FA652EA7725A00C373EC /* TrainView.swift */; }; FBA6FA662EA7725A00C373EC /* TrainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBA6FA652EA7725A00C373EC /* TrainView.swift */; };
FBE1A29D2EAA1B4300081638 /* UniView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBE1A29C2EAA1B4300081638 /* UniView.swift */; };
FBE1A29F2EAA225600081638 /* NewUnicycleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBE1A29E2EAA225600081638 /* NewUnicycleView.swift */; };
FBE1A2A12EAA340F00081638 /* WebAppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBE1A2A02EAA340F00081638 /* WebAppView.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
@ -47,6 +50,9 @@
FBA6FA612EA76AAD00C373EC /* BikeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BikeView.swift; sourceTree = "<group>"; }; FBA6FA612EA76AAD00C373EC /* BikeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BikeView.swift; sourceTree = "<group>"; };
FBA6FA632EA7715000C373EC /* Extentions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extentions.swift; sourceTree = "<group>"; }; FBA6FA632EA7715000C373EC /* Extentions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extentions.swift; sourceTree = "<group>"; };
FBA6FA652EA7725A00C373EC /* TrainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrainView.swift; sourceTree = "<group>"; }; FBA6FA652EA7725A00C373EC /* TrainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrainView.swift; sourceTree = "<group>"; };
FBE1A29C2EAA1B4300081638 /* UniView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UniView.swift; sourceTree = "<group>"; };
FBE1A29E2EAA225600081638 /* NewUnicycleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewUnicycleView.swift; sourceTree = "<group>"; };
FBE1A2A02EAA340F00081638 /* WebAppView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebAppView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -63,6 +69,7 @@
0CC14A6D2E92EC4700271E8D = { 0CC14A6D2E92EC4700271E8D = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
FBE1A2A02EAA340F00081638 /* WebAppView.swift */,
FBA00D742EA7ACDD006F8B9A /* SwapperView.swift */, FBA00D742EA7ACDD006F8B9A /* SwapperView.swift */,
FBA00D702EA7A830006F8B9A /* PaddingView.swift */, FBA00D702EA7A830006F8B9A /* PaddingView.swift */,
FBA00D6E2EA78850006F8B9A /* Color.swift */, FBA00D6E2EA78850006F8B9A /* Color.swift */,
@ -75,6 +82,8 @@
FBA6FA612EA76AAD00C373EC /* BikeView.swift */, FBA6FA612EA76AAD00C373EC /* BikeView.swift */,
FB79FE472EA8F74F0011678F /* BikeSwipeView.swift */, FB79FE472EA8F74F0011678F /* BikeSwipeView.swift */,
FB79FE492EA906CC0011678F /* UnicycleView.swift */, FB79FE492EA906CC0011678F /* UnicycleView.swift */,
FBE1A29E2EAA225600081638 /* NewUnicycleView.swift */,
FBE1A29C2EAA1B4300081638 /* UniView.swift */,
FB79FE4B2EA9071F0011678F /* Unicycle.swift */, FB79FE4B2EA9071F0011678F /* Unicycle.swift */,
FBA6FA652EA7725A00C373EC /* TrainView.swift */, FBA6FA652EA7725A00C373EC /* TrainView.swift */,
FB2F07E82EA7CB25002BD499 /* ListView.swift */, FB2F07E82EA7CB25002BD499 /* ListView.swift */,
@ -168,6 +177,7 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
FBE1A29D2EAA1B4300081638 /* UniView.swift in Sources */,
FBA6FA5E2EA63EA300C373EC /* Models.swift in Sources */, FBA6FA5E2EA63EA300C373EC /* Models.swift in Sources */,
FB79FE482EA8F74F0011678F /* BikeSwipeView.swift in Sources */, FB79FE482EA8F74F0011678F /* BikeSwipeView.swift in Sources */,
FB79FE462EA8CFD20011678F /* RangeView.swift in Sources */, FB79FE462EA8CFD20011678F /* RangeView.swift in Sources */,
@ -178,7 +188,9 @@
FBA6FA642EA7715E00C373EC /* Extentions.swift in Sources */, FBA6FA642EA7715E00C373EC /* Extentions.swift in Sources */,
FB79FE4A2EA906CC0011678F /* UnicycleView.swift in Sources */, FB79FE4A2EA906CC0011678F /* UnicycleView.swift in Sources */,
0CC14A872E92EC7B00271E8D /* App.swift in Sources */, 0CC14A872E92EC7B00271E8D /* App.swift in Sources */,
FBE1A29F2EAA225600081638 /* NewUnicycleView.swift in Sources */,
FBA00D732EA7A96C006F8B9A /* ContentView.swift in Sources */, FBA00D732EA7A96C006F8B9A /* ContentView.swift in Sources */,
FBE1A2A12EAA340F00081638 /* WebAppView.swift in Sources */,
FBA00D6F2EA78853006F8B9A /* Color.swift in Sources */, FBA00D6F2EA78853006F8B9A /* Color.swift in Sources */,
FB2F07E92EA7CB25002BD499 /* ListView.swift in Sources */, FB2F07E92EA7CB25002BD499 /* ListView.swift in Sources */,
FBA00D712EA7A839006F8B9A /* PaddingView.swift in Sources */, FBA00D712EA7A839006F8B9A /* PaddingView.swift in Sources */,
@ -327,6 +339,7 @@
INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 18.6;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
@ -358,6 +371,7 @@
INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 18.6;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",

View file

@ -3,22 +3,4 @@
uuid = "543AEB13-B7EA-4C8C-9F73-C23287B3971E" uuid = "543AEB13-B7EA-4C8C-9F73-C23287B3971E"
type = "1" type = "1"
version = "2.0"> version = "2.0">
<Breakpoints>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "B8EA1D18-A70B-45BA-91B0-542F11641B66"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "BikeView.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "1"
endingLineNumber = "1"
landmarkName = "unknown"
landmarkType = "0">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket> </Bucket>

132
UniView.swift Normal file
View file

@ -0,0 +1,132 @@
//import SwiftUI
//import SwiftData
//
////@Model class Unicycle {
//// var createdAt = Date()
//// var name = ""
//// var red = 1.0
//// var green = 1.0
//// var blue = 1.0
//// init() { } // You can't escape this
////}
//
//struct UniView: View {
// @Environment(\.modelContext) private var modelContext
// @Query private var unis: [Unicycle]
// @State private var selection = Set<PersistentIdentifier>()
// @Environment(\.editMode) private var editMode
// @State private var edit: EditMode = .inactive
//
// var body: some View {
// NavigationStack {
// List(selection: $selection) {
// ForEach(unis) { uni in
// NavigationLink(uni.createdAt.description) {
// UniDetailView(uni: uni)
// }
// }
// .onDelete { indexSet in
// for index in indexSet {
// modelContext.delete(unis[index])
// }
// }
// }
// .toolbar {
//// ToolbarItem(placement: .topBarLeading) {
// if !unis.isEmpty { EditButton() }
//// }
//// ToolbarItem(placement: .topBarTrailing) {
// if edit == .active {
// if !selectedUnis.isEmpty {
// Button("Delete \(selectedUnis.count)", role: .destructive) {
// // Map selection to models and delete
// for uni in selectedUnis {
// modelContext.delete(uni)
// }
// selection.removeAll()
// }
// .disabled(selection.isEmpty)
// }
// } else {
// Button("Add") {
// modelContext.insert(Unicycle())
// }
// }
//// }
// }
// .environment(\.editMode, $edit) // <-- Provide the binding
// }
// }
//
// @MainActor
// var selectedUnis: [Unicycle] {
// unis.filter { selection.contains($0.id) }
// }
//}
//
//struct UniDetailView: View {
// @Bindable var uni: Unicycle
// @State var color: Color
// @Environment(\.modelContext) private var modelContext
//
// init(uni: Unicycle) {
// self.uni = uni
// _color = State(initialValue: Color(red: uni.red, green: uni.green, blue: uni.blue))
// }
//
// var body: some View {
// VStack {
// Text(uni.createdAt.description)
// ColorPicker("Color", selection: Binding(
// get: { color },
// set: {
// color = $0
// if let comps = $0.rgbComponents() {
// uni.red = Double(comps.red)
// uni.green = Double(comps.green)
// uni.blue = Double(comps.blue)
// }
// }
// ))
// TextField("Enter name", text: $uni.name)
// .textFieldStyle(.roundedBorder)
// .padding()
// Button("Save 3") {
// try? modelContext.save()
//
//
// }
// }
// .padding()
// .onChange(of: color) {
// if let comps = color.rgbComponents() {
// uni.red = Double(comps.red)
// uni.green = Double(comps.green)
// uni.blue = Double(comps.blue)
// }
// }
// }
//}
//
//extension Color {
// func rgbComponents() -> (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)? {
// // Convert SwiftUI Color to UIColor
// let uiColor = UIColor(self)
//
// var r: CGFloat = 0
// var g: CGFloat = 0
// var b: CGFloat = 0
// var a: CGFloat = 0
//
// guard uiColor.getRed(&r, green: &g, blue: &b, alpha: &a) else {
// return nil
// }
// return (r, g, b, a)
// }
//}
//
//
//#Preview {
// UniView()
// .modelContainer(for: Unicycle.self)
//}

View file

@ -1,13 +1,37 @@
import SwiftData import SwiftData
import SwiftUI import SwiftUI
@Model class Unicycle {
var createdAt: Date
var name: String
var red: CGFloat
var green: CGFloat
var blue: CGFloat
var alpha: CGFloat
@Model class Unicycle{ // Default values for all properties
var createdAt: Date = Date() init(createdAt: Date = Date(), name: String = "", red: CGFloat = CGFloat.random(in: 0...1), green: CGFloat = CGFloat.random(in: 0...1), blue: CGFloat = CGFloat.random(in: 0...1), alpha: CGFloat = 1) {
init(createdAt: Date) {
self.createdAt = createdAt self.createdAt = createdAt
self.name = name
self.red = red
self.green = green
self.blue = blue
self.alpha = alpha
} }
var color: Color {
get { Color(red: red, green: green, blue: blue,
opacity: alpha) }
set {
UIColor(newValue).getRed(
&red,
green: &green,
blue: &blue,
alpha: &alpha
)
}
}
} }

View file

@ -1,32 +1,158 @@
import SwiftData //import SwiftData
import SwiftUI //import SwiftUI
//
struct UnicycleView2: View { //struct UnicycleView2: View {
var body: some View { // var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) // Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
} // }
} //}
//
struct UnicycleView: View { //struct UnicycleView: View {
@Environment(\.modelContext) private var modelContext // @Environment(\.modelContext) private var modelContext
@Query private var unis: [Unicycle] // @Query private var unis: [Unicycle]
//
var body: some View { // var body: some View {
Button("Add unicycle") { // Button("Add unicycle") {
modelContext.insert(Unicycle(createdAt: Date())) // modelContext.insert(Unicycle(createdAt: Date()))
} // }
List{ // List{
ForEach(unis) { uni in // ForEach(unis) { uni in
Text("Einrad von \(uni.createdAt.description)") // Text("Einrad von \(uni.createdAt.description)")
}.onDelete { // }.onDelete {
for index in $0 { // for index in $0 {
modelContext.delete(unis[index]) // modelContext.delete(unis[index])
} // }
} // }
} // }
} // }
} //}
//
#Preview { //
UnicycleView2() //
} //
//struct UniListView: View {
// @Environment(\.modelContext) private var modelContext
// @Query private var unis: [Unicycle]
//
// init(filter: String, sort: SortDescriptor<Unicycle>) {
// _unis = Query(filter: #Predicate<Unicycle> {
// filter.isEmpty || $0.name.contains(filter)
// }, sort: [sort])
// }
//
// var body: some View {
// List {
// ForEach(unis) { u in
// NavigationLink {
// UniDetailView(uni: u)
// } label: {
// HStack {
// VStack(alignment: .leading) {
// Text(u.name)
// Text(u.createdAt.description)
// .font(.caption)
// }
// Spacer()
// ColorPicker("", selection: .constant(u.color))
// .disabled(true)
// }
// }
// }
// .onDelete {
// for index in $0 { // [2, 3]
// modelContext.delete(unis[index])
// }
// }
// }
// .navigationTitle("\(unis.count) Unicycles")
// }
//}
//
//struct UnicycleView3: View {
// @Environment(\.modelContext) private var modelContext
//
// @State private var isPresented = false
// @State private var sortOrder = SortDescriptor(\Unicycle.name)
// @State private var search = ""
//
// var body: some View {
// NavigationStack {
// UniListView(filter: search, sort: sortOrder)
// .searchable(text: $search)
// .toolbar {
// ToolbarItem(placement: .topBarLeading) {
// EditButton()
// }
// ToolbarItem(placement: .topBarTrailing) {
// HStack {
// Button("Add", systemImage: "plus") { isPresented = true }
// picker
// }
// }
// }
// .sheet(isPresented: $isPresented) {
// UniDetailView(uni: Unicycle())
// }
// Button("Save") {
// try? modelContext.save()
// }
// }
// }
//
// var picker: some View {
// Menu("Sort", systemImage: "arrow.up.arrow.down") {
// Picker("Sort", selection: $sortOrder) {
// Text("Name")
// .tag(SortDescriptor(\Unicycle.name))
// Text("Date")
// .tag(SortDescriptor(\Unicycle.createdAt, order: .reverse))
// }
// .pickerStyle(.inline)
// }
// }
//}
//
//struct UniDetailView2: View {
// @Environment(\.modelContext) private var modelContext
// @Bindable var uni: Unicycle
// @Environment(\.dismiss) private var dismiss
//
// var body: some View {
// Form {
// DefaultTextField("Enter a name", $uni.name)
// ColorPicker("Color", selection: $uni.color)
// Button("Save") {
// modelContext.insert(uni)
// dismiss()
// }
// }
// }
//}
//
//struct DefaultTextField: View {
// @FocusState private var isFocused: Bool
// private var placeholder: String
// private var text: Binding<String>
//
// init(_ placeholder: String = "", _ text: Binding<String>) {
// self.placeholder = placeholder
// self.text = text
// }
//
// var body: some View {
// TextField(placeholder, text: text)
// .focused($isFocused)
// .onAppear { isFocused = true }
// }
//}
//
//#Preview {
// UnicycleView()
// .modelContainer(for: Unicycle.self)
//}
//
//
//
//#Preview {
// UnicycleView()
//}

51
WebAppView.swift Normal file
View file

@ -0,0 +1,51 @@
//
// WebView.swift
// TheSwiftWeek
//
// Created by Ingo Rohlf on 23.10.25.
//
import SwiftUI
import WebKit
struct WebAppView: View {
// @State private var page = WebPage()
var body: some View {
if let url = URL(string: "https://git.irohlf.de") {
if #available(iOS 27.0, *) {
Text("WebView für iOS 26+")
WebView(url: url)
} else {
Text("please update to iOS 26.0 or later")
WebOldView(url: URL(string: "https://ai.irohlf.de")!)
}
}
}
}
struct WebOldView: UIViewRepresentable {
let url: URL
typealias UIViewType = WKWebView
func makeUIView(context: Context) -> WKWebView {
.init()
}
func updateUIView(_ uiView: WKWebView, context: Context) {
uiView.load(URLRequest(url: url))
}
}
#Preview {
WebAppView()
}