├── StudentRegistry ├── Untitled 2.swift ├── Untitled.swift ├── StudentRegistry │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── EnrollmentsView.swift │ ├── StudentRegistryApp.swift │ ├── AddStudentView.swift │ ├── Models.swift │ ├── CoursesView.swift │ ├── AddCourseView.swift │ ├── StudentsView.swift │ └── StudentDetailView.swift ├── StudentRegistry.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── StudentRegistryTests │ └── StudentRegistryTests.swift └── StudentRegistryUITests │ ├── StudentRegistryUITestsLaunchTests.swift │ └── StudentRegistryUITests.swift ├── MapDemo ├── MapDemo │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── MapDemoApp.swift │ └── ContentView.swift ├── MapDemo.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── MapDemoTests │ └── MapDemoTests.swift └── MapDemoUITests │ ├── MapDemoUITestsLaunchTests.swift │ └── MapDemoUITests.swift ├── TodoApp ├── TodoApp │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── TodoItem.swift │ ├── TodoAppApp.swift │ ├── TodoHelpView.swift │ ├── TodoDetailView.swift │ └── TodoListView.swift └── TodoApp.xcodeproj │ ├── project.xcworkspace │ └── contents.xcworkspacedata │ └── project.pbxproj ├── LibraryApp ├── LibraryApp │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── LibraryAppApp.swift │ ├── Book.swift │ ├── BookRowView.swift │ ├── BookListView.swift │ └── AddBookView.swift ├── LibraryApp.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── LibraryAppTests │ └── LibraryAppTests.swift └── LibraryAppUITests │ ├── LibraryAppUITestsLaunchTests.swift │ └── LibraryAppUITests.swift ├── StateDemo ├── StateDemo │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── StateDemoApp.swift │ ├── ContentView.swift │ ├── LocationView.swift │ └── UserProfileView.swift ├── StateDemo.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── StateDemoTests │ └── StateDemoTests.swift └── StateDemoUITests │ ├── StateDemoUITestsLaunchTests.swift │ └── StateDemoUITests.swift ├── ActionsTest ├── ActionsTest │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── ActionsTestApp.swift │ ├── ContentView2.swift │ └── ContentView.swift └── ActionsTest.xcodeproj │ ├── project.xcworkspace │ └── contents.xcworkspacedata │ └── project.pbxproj ├── Forelesning3 ├── Forelesning3 │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── Forelesning3App.swift │ ├── ContentView.swift │ └── MyList.swift └── Forelesning3.xcodeproj │ ├── project.xcworkspace │ └── contents.xcworkspacedata │ └── project.pbxproj ├── Forelesning7 ├── Forelesning7 │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Forelesning7App.swift │ ├── MenuView.swift │ ├── ProfileView.swift │ └── ContentView.swift └── Forelesning7.xcodeproj │ ├── project.xcworkspace │ └── contents.xcworkspacedata │ └── project.pbxproj ├── Forelesning8 ├── Forelesning8 │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Forelesning8App.swift │ ├── User.swift │ └── ContentView.swift ├── Forelesning8.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── Forelesning8Tests │ └── Forelesning8Tests.swift └── Forelesning8UITests │ ├── Forelesning8UITestsLaunchTests.swift │ └── Forelesning8UITests.swift ├── AnimationsDemo ├── AnimationsDemo │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── AnimationsDemoApp.swift │ └── ContentView.swift ├── AnimationsDemo.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── AnimationsDemoTests │ └── AnimationsDemoTests.swift └── AnimationsDemoUITests │ ├── AnimationsDemoUITestsLaunchTests.swift │ └── AnimationsDemoUITests.swift ├── Demo-Appstorage ├── Demo-Appstorage │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── myimage.imageset │ │ │ └── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── primaryBrandColor.colorset │ │ │ └── Contents.json │ ├── Info.plist │ ├── Demo_AppstorageApp.swift │ ├── SearchFieldDemoView.swift │ └── ContentView.swift ├── Demo-Appstorage.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── Demo-AppstorageTests │ └── Demo_AppstorageTests.swift └── Demo-AppstorageUITests │ ├── Demo_AppstorageUITestsLaunchTests.swift │ └── Demo_AppstorageUITests.swift ├── Forelesning_9 ├── Forelesning_9 │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Forelesning_9App.swift │ ├── MySearchBar.swift │ ├── Country.swift │ ├── WordArt.swift │ ├── CountryRowView.swift │ └── ContentView.swift ├── Forelesning_9.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── Forelesning_9Tests │ └── Forelesning_9Tests.swift └── Forelesning_9UITests │ ├── Forelesning_9UITestsLaunchTests.swift │ └── Forelesning_9UITests.swift ├── Lecture5-Forms ├── Lecture5-Forms │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Preview Content │ │ └── Preview Assets.xcassets │ │ │ └── Contents.json │ ├── Lecture5_FormsApp.swift │ └── RegistrationView.swift └── Lecture5-Forms.xcodeproj │ ├── project.xcworkspace │ └── contents.xcworkspacedata │ └── project.pbxproj ├── FilteringSortingExample ├── FilteringSortingExample │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── FilteringSortingExampleApp.swift │ └── ContentView.swift ├── FilteringSortingExample.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── FilteringSortingExampleTests │ └── FilteringSortingExampleTests.swift └── FilteringSortingExampleUITests │ ├── FilteringSortingExampleUITestsLaunchTests.swift │ └── FilteringSortingExampleUITests.swift ├── README.md ├── .gitignore └── plan.md /StudentRegistry/Untitled 2.swift: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /StudentRegistry/Untitled.swift: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /MapDemo/MapDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /TodoApp/TodoApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /LibraryApp/LibraryApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /StateDemo/StateDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ActionsTest/ActionsTest/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Forelesning3/Forelesning3/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Forelesning7/Forelesning7/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Forelesning8/Forelesning8/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /AnimationsDemo/AnimationsDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Demo-Appstorage/Demo-Appstorage/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Forelesning_9/Forelesning_9/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Lecture5-Forms/Lecture5-Forms/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /StudentRegistry/StudentRegistry/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /TodoApp/TodoApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ActionsTest/ActionsTest/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FilteringSortingExample/FilteringSortingExample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Forelesning3/Forelesning3/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Lecture5-Forms/Lecture5-Forms/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /MapDemo/MapDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TodoApp/TodoApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /StateDemo/StateDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ActionsTest/ActionsTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Forelesning3/Forelesning3.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Forelesning7/Forelesning7.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Forelesning8/Forelesning8.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LibraryApp/LibraryApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AnimationsDemo/AnimationsDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Forelesning_9/Forelesning_9.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Lecture5-Forms/Lecture5-Forms.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MapDemo/MapDemo/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /TodoApp/TodoApp/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ActionsTest/ActionsTest/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Demo-Appstorage/Demo-Appstorage.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LibraryApp/LibraryApp/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /StateDemo/StateDemo/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /StudentRegistry/StudentRegistry.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo-Appstorage/Demo-Appstorage/Assets.xcassets/myimage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Forelesning3/Forelesning3/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Forelesning7/Forelesning7/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Forelesning8/Forelesning8/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Forelesning_9/Forelesning_9/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /AnimationsDemo/AnimationsDemo/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Demo-Appstorage/Demo-Appstorage/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Lecture5-Forms/Lecture5-Forms/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /StudentRegistry/StudentRegistry/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /FilteringSortingExample/FilteringSortingExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TodoApp/TodoApp/TodoItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TodoItem.swift 3 | // TodoApp 4 | // 5 | // Created by Håkon Bogen on 09/09/2025. 6 | // 7 | 8 | struct TodoItem: Hashable { 9 | 10 | let text: String 11 | let helpText: String? 12 | 13 | } 14 | -------------------------------------------------------------------------------- /FilteringSortingExample/FilteringSortingExample/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Demo-Appstorage/Demo-Appstorage/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Location 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /MapDemo/MapDemo/MapDemoApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MapDemoApp.swift 3 | // MapDemo 4 | // 5 | // Created by Håkon Bogen on 08/10/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct MapDemoApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /TodoApp/TodoApp/TodoAppApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TodoAppApp.swift 3 | // TodoApp 4 | // 5 | // Created by Håkon Bogen on 09/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct TodoAppApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | TodoListView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /StateDemo/StateDemo/StateDemoApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StateDemoApp.swift 3 | // StateDemo 4 | // 5 | // Created by Håkon Bogen on 04/11/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct StateDemoApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ActionsTest/ActionsTest/ActionsTestApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ActionsTestApp.swift 3 | // ActionsTest 4 | // 5 | // Created by Håkon Bogen on 03/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct ActionsTestApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Forelesning7/Forelesning7/Forelesning7App.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Forelesning7App.swift 3 | // Forelesning7 4 | // 5 | // Created by Håkon Bogen on 16/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct Forelesning7App: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Forelesning8/Forelesning8/Forelesning8App.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Forelesning8App.swift 3 | // Forelesning8 4 | // 5 | // Created by Håkon Bogen on 17/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct Forelesning8App: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Forelesning_9/Forelesning_9/Forelesning_9App.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Forelesning_9App.swift 3 | // Forelesning_9 4 | // 5 | // Created by Håkon Bogen on 23/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct Forelesning_9App: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /AnimationsDemo/AnimationsDemo/AnimationsDemoApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnimationsDemoApp.swift 3 | // AnimationsDemo 4 | // 5 | // Created by Håkon Bogen on 07/10/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct AnimationsDemoApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Lecture5-Forms/Lecture5-Forms/Lecture5_FormsApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Lecture5_FormsApp.swift 3 | // Lecture5-Forms 4 | // 5 | // Created by Håkon Bogen on 10/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct Lecture5_FormsApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | RegistrationView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /StudentRegistry/StudentRegistry/EnrollmentsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EnrollmentsView.swift 3 | // StudentRegistry 4 | // 5 | // Created by Håkon Bogen on 15/10/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct EnrollmentsView: View { 11 | var body: some View { 12 | Text("Enrollments view") 13 | } 14 | } 15 | 16 | #Preview { 17 | EnrollmentsView() 18 | } 19 | -------------------------------------------------------------------------------- /Forelesning3/Forelesning3/Forelesning3App.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Forelesning3App.swift 3 | // Forelesning3 4 | // 5 | // Created by Håkon Bogen on 02/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct Forelesning3App: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | // ContentView() 15 | MyList() 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /MapDemo/MapDemoTests/MapDemoTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MapDemoTests.swift 3 | // MapDemoTests 4 | // 5 | // Created by Håkon Bogen on 08/10/2025. 6 | // 7 | 8 | import Testing 9 | @testable import MapDemo 10 | 11 | struct MapDemoTests { 12 | 13 | @Test func example() async throws { 14 | // Write your test here and use APIs like `#expect(...)` to check expected conditions. 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /FilteringSortingExample/FilteringSortingExample/FilteringSortingExampleApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FilteringSortingExampleApp.swift 3 | // FilteringSortingExample 4 | // 5 | // Created by Håkon Bogen on 12/11/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct FilteringSortingExampleApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /StateDemo/StateDemoTests/StateDemoTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StateDemoTests.swift 3 | // StateDemoTests 4 | // 5 | // Created by Håkon Bogen on 04/11/2025. 6 | // 7 | 8 | import Testing 9 | @testable import StateDemo 10 | 11 | struct StateDemoTests { 12 | 13 | @Test func example() async throws { 14 | // Write your test here and use APIs like `#expect(...)` to check expected conditions. 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /LibraryApp/LibraryAppTests/LibraryAppTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LibraryAppTests.swift 3 | // LibraryAppTests 4 | // 5 | // Created by Håkon Bogen on 14/10/2025. 6 | // 7 | 8 | import Testing 9 | @testable import LibraryApp 10 | 11 | struct LibraryAppTests { 12 | 13 | @Test func example() async throws { 14 | // Write your test here and use APIs like `#expect(...)` to check expected conditions. 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Forelesning8/Forelesning8Tests/Forelesning8Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Forelesning8Tests.swift 3 | // Forelesning8Tests 4 | // 5 | // Created by Håkon Bogen on 17/09/2025. 6 | // 7 | 8 | import Testing 9 | @testable import Forelesning8 10 | 11 | struct Forelesning8Tests { 12 | 13 | @Test func example() async throws { 14 | // Write your test here and use APIs like `#expect(...)` to check expected conditions. 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Forelesning_9/Forelesning_9Tests/Forelesning_9Tests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Forelesning_9Tests.swift 3 | // Forelesning_9Tests 4 | // 5 | // Created by Håkon Bogen on 23/09/2025. 6 | // 7 | 8 | import Testing 9 | @testable import Forelesning_9 10 | 11 | struct Forelesning_9Tests { 12 | 13 | @Test func example() async throws { 14 | // Write your test here and use APIs like `#expect(...)` to check expected conditions. 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /AnimationsDemo/AnimationsDemoTests/AnimationsDemoTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnimationsDemoTests.swift 3 | // AnimationsDemoTests 4 | // 5 | // Created by Håkon Bogen on 07/10/2025. 6 | // 7 | 8 | import Testing 9 | @testable import AnimationsDemo 10 | 11 | struct AnimationsDemoTests { 12 | 13 | @Test func example() async throws { 14 | // Write your test here and use APIs like `#expect(...)` to check expected conditions. 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Demo-Appstorage/Demo-AppstorageTests/Demo_AppstorageTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Demo_AppstorageTests.swift 3 | // Demo-AppstorageTests 4 | // 5 | // Created by Håkon Bogen on 29/10/2025. 6 | // 7 | 8 | import Testing 9 | @testable import Demo_Appstorage 10 | 11 | struct Demo_AppstorageTests { 12 | 13 | @Test func example() async throws { 14 | // Write your test here and use APIs like `#expect(...)` to check expected conditions. 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /StudentRegistry/StudentRegistryTests/StudentRegistryTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StudentRegistryTests.swift 3 | // StudentRegistryTests 4 | // 5 | // Created by Håkon Bogen on 15/10/2025. 6 | // 7 | 8 | import Testing 9 | @testable import StudentRegistry 10 | 11 | struct StudentRegistryTests { 12 | 13 | @Test func example() async throws { 14 | // Write your test here and use APIs like `#expect(...)` to check expected conditions. 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Demo-Appstorage/Demo-Appstorage/Demo_AppstorageApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Demo_AppstorageApp.swift 3 | // Demo-Appstorage 4 | // 5 | // Created by Håkon Bogen on 29/10/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct Demo_AppstorageApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | TabView { 15 | ContentView() 16 | 17 | SearchFieldDemoView() 18 | 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FilteringSortingExample/FilteringSortingExampleTests/FilteringSortingExampleTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FilteringSortingExampleTests.swift 3 | // FilteringSortingExampleTests 4 | // 5 | // Created by Håkon Bogen on 12/11/2025. 6 | // 7 | 8 | import Testing 9 | @testable import FilteringSortingExample 10 | 11 | struct FilteringSortingExampleTests { 12 | 13 | @Test func example() async throws { 14 | // Write your test here and use APIs like `#expect(...)` to check expected conditions. 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /LibraryApp/LibraryApp/LibraryAppApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LibraryAppApp.swift 3 | // LibraryApp 4 | // 5 | // Created by Håkon Bogen on 14/10/2025. 6 | // 7 | 8 | import SwiftUI 9 | import SwiftData 10 | 11 | @main 12 | struct LibraryAppApp: App { 13 | var body: some Scene { 14 | WindowGroup { 15 | NavigationStack { 16 | BookListView() 17 | } 18 | .modelContainer(for: Book.self) 19 | } 20 | } 21 | } 22 | #Preview { 23 | BookListView() 24 | } 25 | -------------------------------------------------------------------------------- /TodoApp/TodoApp/TodoHelpView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TodoHelpView.swift 3 | // TodoApp 4 | // 5 | // Created by Håkon Bogen on 09/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct TodoHelpView: View { 11 | 12 | var todoItem: String 13 | 14 | var body: some View { 15 | VStack{ 16 | Text("Todo help text: ") 17 | .font(.callout) 18 | Text(todoItem) 19 | } 20 | } 21 | 22 | } 23 | 24 | #Preview { 25 | TodoHelpView(todoItem: "test preview todo item") 26 | } 27 | -------------------------------------------------------------------------------- /Forelesning8/Forelesning8/User.swift: -------------------------------------------------------------------------------- 1 | // 2 | // User.swift 3 | // Forelesning8 4 | // 5 | // Created by Håkon Bogen on 17/09/2025. 6 | // 7 | 8 | 9 | struct User: Decodable, Identifiable { 10 | 11 | // let id2: UUID = UUID() 12 | let id: Int 13 | let name: String 14 | let email: String 15 | let website: String? 16 | let address: Address 17 | 18 | struct Address: Decodable { 19 | 20 | let street: String 21 | let zipCode: String 22 | 23 | } 24 | 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # PG5602 H2025 4 | 5 | Kursmateriale for PG5602 iOS-utvikling med SwiftUI. 6 | 7 | ## 📋 Kursoversikt 8 | 9 | Se fullstendig kursplan, med forebehold om endringer basert på tilbakemeldinger: [plan.md](plan.md) 10 | 11 | ## 📝 Oppgaver 12 | 13 | Alle praktiske oppgaver og øvelser: [oppgaver.md](oppgaver.md) 14 | 15 | ## 📁 Prosjektstruktur 16 | 17 | - `plan.md` - Detaljert kursplan med alle forelesninger og temaer 18 | - `oppgaver.md` - Samling av alle praktiske oppgaver 19 | - `Forelesning3/` - Kodeeksempler fra forelesning 3 20 | - `ActionsTest/` - Testkode for actions og interaksjoner (Forelesning 4) 21 | -------------------------------------------------------------------------------- /Forelesning_9/Forelesning_9/MySearchBar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MySearchBar.swift 3 | // Forelesning_9 4 | // 5 | // Created by Håkon Bogen on 24/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct MySearchBar: View { 11 | @Binding var text: String 12 | 13 | var body: some View { 14 | HStack { 15 | Image(systemName: "magnifyingglass.circle") 16 | .foregroundStyle(.cyan) 17 | TextField("Search", text: $text) 18 | .textFieldStyle(.roundedBorder) 19 | }.padding() 20 | } 21 | } 22 | 23 | 24 | #Preview { 25 | MySearchBar(text: .constant("Hello world!")) 26 | } 27 | -------------------------------------------------------------------------------- /LibraryApp/LibraryApp/Book.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Book.swift 3 | // LibraryApp 4 | // 5 | // Created by Håkon Bogen on 14/10/2025. 6 | // 7 | import SwiftUI 8 | import SwiftData 9 | 10 | @Model 11 | class Book { 12 | 13 | var id: UUID 14 | var title: String 15 | var author: String 16 | var yearpublished: Int 17 | var isRead: Bool 18 | 19 | init(id: UUID, title: String, author: String, yearpublished: Int, isRead: Bool) { 20 | self.id = id 21 | self.title = title 22 | self.author = author 23 | self.yearpublished = yearpublished 24 | self.isRead = isRead 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /MapDemo/MapDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "idiom" : "universal", 16 | "platform" : "ios", 17 | "size" : "1024x1024" 18 | }, 19 | { 20 | "appearances" : [ 21 | { 22 | "appearance" : "luminosity", 23 | "value" : "tinted" 24 | } 25 | ], 26 | "idiom" : "universal", 27 | "platform" : "ios", 28 | "size" : "1024x1024" 29 | } 30 | ], 31 | "info" : { 32 | "author" : "xcode", 33 | "version" : 1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /TodoApp/TodoApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "idiom" : "universal", 16 | "platform" : "ios", 17 | "size" : "1024x1024" 18 | }, 19 | { 20 | "appearances" : [ 21 | { 22 | "appearance" : "luminosity", 23 | "value" : "tinted" 24 | } 25 | ], 26 | "idiom" : "universal", 27 | "platform" : "ios", 28 | "size" : "1024x1024" 29 | } 30 | ], 31 | "info" : { 32 | "author" : "xcode", 33 | "version" : 1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /LibraryApp/LibraryApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "idiom" : "universal", 16 | "platform" : "ios", 17 | "size" : "1024x1024" 18 | }, 19 | { 20 | "appearances" : [ 21 | { 22 | "appearance" : "luminosity", 23 | "value" : "tinted" 24 | } 25 | ], 26 | "idiom" : "universal", 27 | "platform" : "ios", 28 | "size" : "1024x1024" 29 | } 30 | ], 31 | "info" : { 32 | "author" : "xcode", 33 | "version" : 1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /StateDemo/StateDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "idiom" : "universal", 16 | "platform" : "ios", 17 | "size" : "1024x1024" 18 | }, 19 | { 20 | "appearances" : [ 21 | { 22 | "appearance" : "luminosity", 23 | "value" : "tinted" 24 | } 25 | ], 26 | "idiom" : "universal", 27 | "platform" : "ios", 28 | "size" : "1024x1024" 29 | } 30 | ], 31 | "info" : { 32 | "author" : "xcode", 33 | "version" : 1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ActionsTest/ActionsTest/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "idiom" : "universal", 16 | "platform" : "ios", 17 | "size" : "1024x1024" 18 | }, 19 | { 20 | "appearances" : [ 21 | { 22 | "appearance" : "luminosity", 23 | "value" : "tinted" 24 | } 25 | ], 26 | "idiom" : "universal", 27 | "platform" : "ios", 28 | "size" : "1024x1024" 29 | } 30 | ], 31 | "info" : { 32 | "author" : "xcode", 33 | "version" : 1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Forelesning3/Forelesning3/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "idiom" : "universal", 16 | "platform" : "ios", 17 | "size" : "1024x1024" 18 | }, 19 | { 20 | "appearances" : [ 21 | { 22 | "appearance" : "luminosity", 23 | "value" : "tinted" 24 | } 25 | ], 26 | "idiom" : "universal", 27 | "platform" : "ios", 28 | "size" : "1024x1024" 29 | } 30 | ], 31 | "info" : { 32 | "author" : "xcode", 33 | "version" : 1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Forelesning7/Forelesning7/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "idiom" : "universal", 16 | "platform" : "ios", 17 | "size" : "1024x1024" 18 | }, 19 | { 20 | "appearances" : [ 21 | { 22 | "appearance" : "luminosity", 23 | "value" : "tinted" 24 | } 25 | ], 26 | "idiom" : "universal", 27 | "platform" : "ios", 28 | "size" : "1024x1024" 29 | } 30 | ], 31 | "info" : { 32 | "author" : "xcode", 33 | "version" : 1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Forelesning8/Forelesning8/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "idiom" : "universal", 16 | "platform" : "ios", 17 | "size" : "1024x1024" 18 | }, 19 | { 20 | "appearances" : [ 21 | { 22 | "appearance" : "luminosity", 23 | "value" : "tinted" 24 | } 25 | ], 26 | "idiom" : "universal", 27 | "platform" : "ios", 28 | "size" : "1024x1024" 29 | } 30 | ], 31 | "info" : { 32 | "author" : "xcode", 33 | "version" : 1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /AnimationsDemo/AnimationsDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "idiom" : "universal", 16 | "platform" : "ios", 17 | "size" : "1024x1024" 18 | }, 19 | { 20 | "appearances" : [ 21 | { 22 | "appearance" : "luminosity", 23 | "value" : "tinted" 24 | } 25 | ], 26 | "idiom" : "universal", 27 | "platform" : "ios", 28 | "size" : "1024x1024" 29 | } 30 | ], 31 | "info" : { 32 | "author" : "xcode", 33 | "version" : 1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Demo-Appstorage/Demo-Appstorage/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "idiom" : "universal", 16 | "platform" : "ios", 17 | "size" : "1024x1024" 18 | }, 19 | { 20 | "appearances" : [ 21 | { 22 | "appearance" : "luminosity", 23 | "value" : "tinted" 24 | } 25 | ], 26 | "idiom" : "universal", 27 | "platform" : "ios", 28 | "size" : "1024x1024" 29 | } 30 | ], 31 | "info" : { 32 | "author" : "xcode", 33 | "version" : 1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Forelesning_9/Forelesning_9/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "idiom" : "universal", 16 | "platform" : "ios", 17 | "size" : "1024x1024" 18 | }, 19 | { 20 | "appearances" : [ 21 | { 22 | "appearance" : "luminosity", 23 | "value" : "tinted" 24 | } 25 | ], 26 | "idiom" : "universal", 27 | "platform" : "ios", 28 | "size" : "1024x1024" 29 | } 30 | ], 31 | "info" : { 32 | "author" : "xcode", 33 | "version" : 1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Lecture5-Forms/Lecture5-Forms/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "idiom" : "universal", 16 | "platform" : "ios", 17 | "size" : "1024x1024" 18 | }, 19 | { 20 | "appearances" : [ 21 | { 22 | "appearance" : "luminosity", 23 | "value" : "tinted" 24 | } 25 | ], 26 | "idiom" : "universal", 27 | "platform" : "ios", 28 | "size" : "1024x1024" 29 | } 30 | ], 31 | "info" : { 32 | "author" : "xcode", 33 | "version" : 1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /StudentRegistry/StudentRegistry/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "idiom" : "universal", 16 | "platform" : "ios", 17 | "size" : "1024x1024" 18 | }, 19 | { 20 | "appearances" : [ 21 | { 22 | "appearance" : "luminosity", 23 | "value" : "tinted" 24 | } 25 | ], 26 | "idiom" : "universal", 27 | "platform" : "ios", 28 | "size" : "1024x1024" 29 | } 30 | ], 31 | "info" : { 32 | "author" : "xcode", 33 | "version" : 1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /FilteringSortingExample/FilteringSortingExample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "platform" : "ios", 6 | "size" : "1024x1024" 7 | }, 8 | { 9 | "appearances" : [ 10 | { 11 | "appearance" : "luminosity", 12 | "value" : "dark" 13 | } 14 | ], 15 | "idiom" : "universal", 16 | "platform" : "ios", 17 | "size" : "1024x1024" 18 | }, 19 | { 20 | "appearances" : [ 21 | { 22 | "appearance" : "luminosity", 23 | "value" : "tinted" 24 | } 25 | ], 26 | "idiom" : "universal", 27 | "platform" : "ios", 28 | "size" : "1024x1024" 29 | } 30 | ], 31 | "info" : { 32 | "author" : "xcode", 33 | "version" : 1 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ActionsTest/ActionsTest/ContentView2.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView2.swift 3 | // ActionsTest 4 | // 5 | // Created by Håkon Bogen on 03/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView2: View { 11 | 12 | @State var isShowingAlert = false 13 | 14 | var body: some View { 15 | VStack { 16 | Text("Hello, World!") 17 | 18 | Button("Show alert") { 19 | isShowingAlert = true 20 | } 21 | }.alert("Advarsel! Klarte ikke logge inn", isPresented: $isShowingAlert) { 22 | 23 | Button("Avbryt", role: .cancel) { 24 | 25 | } 26 | Button("Prøv igjen") { 27 | // kall web request igjea 28 | } 29 | } 30 | } 31 | } 32 | 33 | #Preview { 34 | ContentView2() 35 | } 36 | -------------------------------------------------------------------------------- /Forelesning7/Forelesning7/MenuView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MenuView.swift 3 | // Forelesning7 4 | // 5 | // Created by Håkon Bogen on 16/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct MenuView: View { 11 | var body: some View { 12 | TabView { 13 | ContentView() 14 | .tabItem { 15 | Label("Galleri", systemImage: "photo.circle") 16 | } 17 | 18 | ProfileView() 19 | .tabItem { 20 | Label("Profil", systemImage: "person.circle") 21 | } 22 | 23 | VStack { 24 | Text("Another screen?") 25 | }.tabItem { 26 | Label("Screen 3", systemImage: "questionmark") 27 | } 28 | } 29 | } 30 | } 31 | 32 | #Preview { 33 | MenuView() 34 | } 35 | -------------------------------------------------------------------------------- /Demo-Appstorage/Demo-Appstorage/Assets.xcassets/primaryBrandColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0xFA", 9 | "green" : "0x44", 10 | "red" : "0xFE" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "255", 27 | "green" : "255", 28 | "red" : "255" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Forelesning_9/Forelesning_9/Country.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Country.swift 3 | // Forelesning_9 4 | // 5 | // Created by Håkon Bogen on 23/09/2025. 6 | // 7 | 8 | 9 | struct Country: Decodable, Identifiable { 10 | 11 | struct CountryName: Decodable { 12 | let common: String 13 | let official: String 14 | } 15 | 16 | let name: CountryName 17 | // Computed variabel: 18 | var id: String { name.common } 19 | let region: String 20 | let subregion: String? 21 | let population: Int 22 | let flag: String 23 | let flags: Flag 24 | let capital: [String]? 25 | let area: Double 26 | 27 | struct Flag: Decodable { 28 | let png: String 29 | let svg: String 30 | let alt: String? 31 | } 32 | 33 | let coatOfArms: CoatOfArms 34 | 35 | struct CoatOfArms: Decodable { 36 | let png: String? 37 | let svg: String? 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /MapDemo/MapDemoUITests/MapDemoUITestsLaunchTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MapDemoUITestsLaunchTests.swift 3 | // MapDemoUITests 4 | // 5 | // Created by Håkon Bogen on 08/10/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class MapDemoUITestsLaunchTests: XCTestCase { 11 | 12 | override class var runsForEachTargetApplicationUIConfiguration: Bool { 13 | true 14 | } 15 | 16 | override func setUpWithError() throws { 17 | continueAfterFailure = false 18 | } 19 | 20 | @MainActor 21 | func testLaunch() throws { 22 | let app = XCUIApplication() 23 | app.launch() 24 | 25 | // Insert steps here to perform after app launch but before taking a screenshot, 26 | // such as logging into a test account or navigating somewhere in the app 27 | 28 | let attachment = XCTAttachment(screenshot: app.screenshot()) 29 | attachment.name = "Launch Screen" 30 | attachment.lifetime = .keepAlways 31 | add(attachment) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /StateDemo/StateDemoUITests/StateDemoUITestsLaunchTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StateDemoUITestsLaunchTests.swift 3 | // StateDemoUITests 4 | // 5 | // Created by Håkon Bogen on 04/11/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class StateDemoUITestsLaunchTests: XCTestCase { 11 | 12 | override class var runsForEachTargetApplicationUIConfiguration: Bool { 13 | true 14 | } 15 | 16 | override func setUpWithError() throws { 17 | continueAfterFailure = false 18 | } 19 | 20 | @MainActor 21 | func testLaunch() throws { 22 | let app = XCUIApplication() 23 | app.launch() 24 | 25 | // Insert steps here to perform after app launch but before taking a screenshot, 26 | // such as logging into a test account or navigating somewhere in the app 27 | 28 | let attachment = XCTAttachment(screenshot: app.screenshot()) 29 | attachment.name = "Launch Screen" 30 | attachment.lifetime = .keepAlways 31 | add(attachment) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LibraryApp/LibraryAppUITests/LibraryAppUITestsLaunchTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LibraryAppUITestsLaunchTests.swift 3 | // LibraryAppUITests 4 | // 5 | // Created by Håkon Bogen on 14/10/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class LibraryAppUITestsLaunchTests: XCTestCase { 11 | 12 | override class var runsForEachTargetApplicationUIConfiguration: Bool { 13 | true 14 | } 15 | 16 | override func setUpWithError() throws { 17 | continueAfterFailure = false 18 | } 19 | 20 | @MainActor 21 | func testLaunch() throws { 22 | let app = XCUIApplication() 23 | app.launch() 24 | 25 | // Insert steps here to perform after app launch but before taking a screenshot, 26 | // such as logging into a test account or navigating somewhere in the app 27 | 28 | let attachment = XCTAttachment(screenshot: app.screenshot()) 29 | attachment.name = "Launch Screen" 30 | attachment.lifetime = .keepAlways 31 | add(attachment) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Forelesning8/Forelesning8UITests/Forelesning8UITestsLaunchTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Forelesning8UITestsLaunchTests.swift 3 | // Forelesning8UITests 4 | // 5 | // Created by Håkon Bogen on 17/09/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class Forelesning8UITestsLaunchTests: XCTestCase { 11 | 12 | override class var runsForEachTargetApplicationUIConfiguration: Bool { 13 | true 14 | } 15 | 16 | override func setUpWithError() throws { 17 | continueAfterFailure = false 18 | } 19 | 20 | @MainActor 21 | func testLaunch() throws { 22 | let app = XCUIApplication() 23 | app.launch() 24 | 25 | // Insert steps here to perform after app launch but before taking a screenshot, 26 | // such as logging into a test account or navigating somewhere in the app 27 | 28 | let attachment = XCTAttachment(screenshot: app.screenshot()) 29 | attachment.name = "Launch Screen" 30 | attachment.lifetime = .keepAlways 31 | add(attachment) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Forelesning_9/Forelesning_9UITests/Forelesning_9UITestsLaunchTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Forelesning_9UITestsLaunchTests.swift 3 | // Forelesning_9UITests 4 | // 5 | // Created by Håkon Bogen on 23/09/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class Forelesning_9UITestsLaunchTests: XCTestCase { 11 | 12 | override class var runsForEachTargetApplicationUIConfiguration: Bool { 13 | true 14 | } 15 | 16 | override func setUpWithError() throws { 17 | continueAfterFailure = false 18 | } 19 | 20 | @MainActor 21 | func testLaunch() throws { 22 | let app = XCUIApplication() 23 | app.launch() 24 | 25 | // Insert steps here to perform after app launch but before taking a screenshot, 26 | // such as logging into a test account or navigating somewhere in the app 27 | 28 | let attachment = XCTAttachment(screenshot: app.screenshot()) 29 | attachment.name = "Launch Screen" 30 | attachment.lifetime = .keepAlways 31 | add(attachment) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /AnimationsDemo/AnimationsDemoUITests/AnimationsDemoUITestsLaunchTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnimationsDemoUITestsLaunchTests.swift 3 | // AnimationsDemoUITests 4 | // 5 | // Created by Håkon Bogen on 07/10/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class AnimationsDemoUITestsLaunchTests: XCTestCase { 11 | 12 | override class var runsForEachTargetApplicationUIConfiguration: Bool { 13 | true 14 | } 15 | 16 | override func setUpWithError() throws { 17 | continueAfterFailure = false 18 | } 19 | 20 | @MainActor 21 | func testLaunch() throws { 22 | let app = XCUIApplication() 23 | app.launch() 24 | 25 | // Insert steps here to perform after app launch but before taking a screenshot, 26 | // such as logging into a test account or navigating somewhere in the app 27 | 28 | let attachment = XCTAttachment(screenshot: app.screenshot()) 29 | attachment.name = "Launch Screen" 30 | attachment.lifetime = .keepAlways 31 | add(attachment) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /TodoApp/TodoApp/TodoDetailView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TodoDetailView.swift 3 | // TodoApp 4 | // 5 | // Created by Håkon Bogen on 09/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct TodoDetailView: View { 11 | 12 | init(todoItem: String) { 13 | self.todoItem = todoItem 14 | } 15 | 16 | var todoItem: String 17 | 18 | @State var isShowingSheet = false 19 | 20 | func didTapQuestionMark() { 21 | isShowingSheet = true 22 | // isShowingSheet.toggle() 23 | } 24 | 25 | var body: some View { 26 | VStack { 27 | Text(todoItem) 28 | Button { 29 | didTapQuestionMark() 30 | } label: { 31 | Image(systemName: "questionmark") 32 | } 33 | 34 | }.sheet(isPresented: $isShowingSheet) { 35 | // return et View 36 | TodoHelpView(todoItem: todoItem) 37 | 38 | } 39 | } 40 | } 41 | 42 | #Preview { 43 | TodoDetailView(todoItem: "Test todo item") 44 | } 45 | -------------------------------------------------------------------------------- /Demo-Appstorage/Demo-AppstorageUITests/Demo_AppstorageUITestsLaunchTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Demo_AppstorageUITestsLaunchTests.swift 3 | // Demo-AppstorageUITests 4 | // 5 | // Created by Håkon Bogen on 29/10/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class Demo_AppstorageUITestsLaunchTests: XCTestCase { 11 | 12 | override class var runsForEachTargetApplicationUIConfiguration: Bool { 13 | true 14 | } 15 | 16 | override func setUpWithError() throws { 17 | continueAfterFailure = false 18 | } 19 | 20 | @MainActor 21 | func testLaunch() throws { 22 | let app = XCUIApplication() 23 | app.launch() 24 | 25 | // Insert steps here to perform after app launch but before taking a screenshot, 26 | // such as logging into a test account or navigating somewhere in the app 27 | 28 | let attachment = XCTAttachment(screenshot: app.screenshot()) 29 | attachment.name = "Launch Screen" 30 | attachment.lifetime = .keepAlways 31 | add(attachment) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /StudentRegistry/StudentRegistryUITests/StudentRegistryUITestsLaunchTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StudentRegistryUITestsLaunchTests.swift 3 | // StudentRegistryUITests 4 | // 5 | // Created by Håkon Bogen on 15/10/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class StudentRegistryUITestsLaunchTests: XCTestCase { 11 | 12 | override class var runsForEachTargetApplicationUIConfiguration: Bool { 13 | true 14 | } 15 | 16 | override func setUpWithError() throws { 17 | continueAfterFailure = false 18 | } 19 | 20 | @MainActor 21 | func testLaunch() throws { 22 | let app = XCUIApplication() 23 | app.launch() 24 | 25 | // Insert steps here to perform after app launch but before taking a screenshot, 26 | // such as logging into a test account or navigating somewhere in the app 27 | 28 | let attachment = XCTAttachment(screenshot: app.screenshot()) 29 | attachment.name = "Launch Screen" 30 | attachment.lifetime = .keepAlways 31 | add(attachment) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /FilteringSortingExample/FilteringSortingExampleUITests/FilteringSortingExampleUITestsLaunchTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FilteringSortingExampleUITestsLaunchTests.swift 3 | // FilteringSortingExampleUITests 4 | // 5 | // Created by Håkon Bogen on 12/11/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class FilteringSortingExampleUITestsLaunchTests: XCTestCase { 11 | 12 | override class var runsForEachTargetApplicationUIConfiguration: Bool { 13 | true 14 | } 15 | 16 | override func setUpWithError() throws { 17 | continueAfterFailure = false 18 | } 19 | 20 | @MainActor 21 | func testLaunch() throws { 22 | let app = XCUIApplication() 23 | app.launch() 24 | 25 | // Insert steps here to perform after app launch but before taking a screenshot, 26 | // such as logging into a test account or navigating somewhere in the app 27 | 28 | let attachment = XCTAttachment(screenshot: app.screenshot()) 29 | attachment.name = "Launch Screen" 30 | attachment.lifetime = .keepAlways 31 | add(attachment) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /StudentRegistry/StudentRegistry/StudentRegistryApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StudentRegistryApp.swift 3 | // StudentRegistry 4 | // 5 | // Created by Håkon Bogen on 15/10/2025. 6 | // 7 | 8 | import SwiftUI 9 | import SwiftData 10 | 11 | @main 12 | struct StudentRegistryApp: App { 13 | var body: some Scene { 14 | WindowGroup { 15 | MainTabView() 16 | } 17 | } 18 | 19 | 20 | } 21 | 22 | struct MainTabView: View { 23 | var body: some View { 24 | TabView { 25 | StudentsView() 26 | .tabItem { 27 | Label("Students", systemImage: "person.2") 28 | } 29 | 30 | CoursesView() 31 | .tabItem { 32 | Label("Courses", systemImage: "book") 33 | } 34 | 35 | EnrollmentsView() 36 | .tabItem { 37 | Label("Enrollments", systemImage: "list.bullet") 38 | } 39 | 40 | }.modelContainer(for: [Student.self, Course.self, Enrollment.self]) 41 | } 42 | } 43 | 44 | #Preview { 45 | MainTabView() 46 | } 47 | -------------------------------------------------------------------------------- /Forelesning_9/Forelesning_9/WordArt.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WordArt.swift 3 | // Forelesning_9 4 | // 5 | // Created by Håkon Bogen on 24/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct WordArtModifier: ViewModifier { 11 | func body(content: Content) -> some View { 12 | content 13 | .font(.system(size: 32, weight: .bold, design: .rounded)) 14 | .foregroundStyle( 15 | LinearGradient(colors: 16 | [.red, .orange, .yellow, .green,.blue, .purple, .pink], 17 | startPoint: .leading, endPoint: .trailing) 18 | ) // end foregroundstyle 19 | .shadow(color: .black, radius: 1, x: 3, y: 3) 20 | .textCase(.uppercase) 21 | 22 | } 23 | 24 | } 25 | 26 | extension View { 27 | 28 | func wordArtStyle() -> some View { 29 | self.modifier(WordArtModifier()) 30 | } 31 | } 32 | 33 | #Preview { 34 | VStack { 35 | Spacer() 36 | Text("Hello world with styling") 37 | .wordArtStyle() 38 | Spacer() 39 | Text("Hello world without styling") 40 | // .fontWeight(.bold) 41 | Spacer() 42 | }.padding() 43 | } 44 | -------------------------------------------------------------------------------- /Forelesning3/Forelesning3/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // Forelesning3 4 | // 5 | // Created by Håkon Bogen on 02/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | var body: some View { 12 | VStack() { 13 | 14 | Spacer() 15 | Image(systemName: "globe") 16 | .imageScale(.large) 17 | .foregroundStyle(.tint) 18 | 19 | Text("Hello, world!") 20 | Text("Lorem ipsum") 21 | 22 | HStack() { 23 | Spacer() 24 | Text("Start HStack") 25 | Spacer() 26 | Text("Slutt HStack") 27 | Spacer() 28 | 29 | }.padding(.bottom) 30 | 31 | HStack { 32 | Image(systemName: "person") 33 | 34 | Text("Ny HStack") 35 | .foregroundStyle(.blue) 36 | Text("Enda en tekst") 37 | Spacer() 38 | } 39 | .font(.largeTitle) 40 | .foregroundStyle(.blue) 41 | 42 | 43 | 44 | Spacer() 45 | } 46 | .padding() 47 | .foregroundStyle(.red) 48 | } 49 | } 50 | 51 | #Preview { 52 | ContentView() 53 | } 54 | -------------------------------------------------------------------------------- /LibraryApp/LibraryApp/BookRowView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BookRowView.swift 3 | // LibraryApp 4 | // 5 | // Created by Håkon Bogen on 14/10/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct BookRowView: View { 11 | 12 | let book: Book 13 | @Environment(\.modelContext) private var modelContext 14 | 15 | func onToggleButtonTapped() { 16 | book.isRead.toggle() 17 | 18 | } 19 | 20 | var body: some View { 21 | HStack { 22 | VStack(alignment: .leading, spacing: 4) { 23 | Text(book.title) 24 | .font(.headline) 25 | Text(book.author) 26 | .font(.subheadline) 27 | .foregroundStyle(.secondary) 28 | Text("Published: \(book.yearpublished)") 29 | .font(.caption) 30 | .foregroundStyle(.secondary) 31 | } 32 | Spacer() 33 | Button(action: onToggleButtonTapped) { 34 | Image(systemName: book.isRead ? "book.fill" : "book") 35 | .foregroundStyle(book.isRead ? .green : .gray) 36 | 37 | }.buttonStyle(.plain) 38 | } 39 | .padding(.leading, 8) 40 | } 41 | } 42 | 43 | #Preview { 44 | List { 45 | BookRowView(book: Book(id: UUID(), title: "LOTR", author: "JRR Tolkien", yearpublished: 1966, isRead: false)) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /MapDemo/MapDemoUITests/MapDemoUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MapDemoUITests.swift 3 | // MapDemoUITests 4 | // 5 | // Created by Håkon Bogen on 08/10/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class MapDemoUITests: XCTestCase { 11 | 12 | override func setUpWithError() throws { 13 | // Put setup code here. This method is called before the invocation of each test method in the class. 14 | 15 | // In UI tests it is usually best to stop immediately when a failure occurs. 16 | continueAfterFailure = false 17 | 18 | // In UI tests it’s 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. 19 | } 20 | 21 | override func tearDownWithError() throws { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | @MainActor 26 | func testExample() throws { 27 | // UI tests must launch the application that they test. 28 | let app = XCUIApplication() 29 | app.launch() 30 | 31 | // Use XCTAssert and related functions to verify your tests produce the correct results. 32 | } 33 | 34 | @MainActor 35 | func testLaunchPerformance() throws { 36 | // This measures how long it takes to launch your application. 37 | measure(metrics: [XCTApplicationLaunchMetric()]) { 38 | XCUIApplication().launch() 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /StateDemo/StateDemoUITests/StateDemoUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StateDemoUITests.swift 3 | // StateDemoUITests 4 | // 5 | // Created by Håkon Bogen on 04/11/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class StateDemoUITests: XCTestCase { 11 | 12 | override func setUpWithError() throws { 13 | // Put setup code here. This method is called before the invocation of each test method in the class. 14 | 15 | // In UI tests it is usually best to stop immediately when a failure occurs. 16 | continueAfterFailure = false 17 | 18 | // In UI tests it’s 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. 19 | } 20 | 21 | override func tearDownWithError() throws { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | @MainActor 26 | func testExample() throws { 27 | // UI tests must launch the application that they test. 28 | let app = XCUIApplication() 29 | app.launch() 30 | 31 | // Use XCTAssert and related functions to verify your tests produce the correct results. 32 | } 33 | 34 | @MainActor 35 | func testLaunchPerformance() throws { 36 | // This measures how long it takes to launch your application. 37 | measure(metrics: [XCTApplicationLaunchMetric()]) { 38 | XCUIApplication().launch() 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /LibraryApp/LibraryAppUITests/LibraryAppUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LibraryAppUITests.swift 3 | // LibraryAppUITests 4 | // 5 | // Created by Håkon Bogen on 14/10/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class LibraryAppUITests: XCTestCase { 11 | 12 | override func setUpWithError() throws { 13 | // Put setup code here. This method is called before the invocation of each test method in the class. 14 | 15 | // In UI tests it is usually best to stop immediately when a failure occurs. 16 | continueAfterFailure = false 17 | 18 | // In UI tests it’s 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. 19 | } 20 | 21 | override func tearDownWithError() throws { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | @MainActor 26 | func testExample() throws { 27 | // UI tests must launch the application that they test. 28 | let app = XCUIApplication() 29 | app.launch() 30 | 31 | // Use XCTAssert and related functions to verify your tests produce the correct results. 32 | } 33 | 34 | @MainActor 35 | func testLaunchPerformance() throws { 36 | // This measures how long it takes to launch your application. 37 | measure(metrics: [XCTApplicationLaunchMetric()]) { 38 | XCUIApplication().launch() 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Forelesning8/Forelesning8UITests/Forelesning8UITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Forelesning8UITests.swift 3 | // Forelesning8UITests 4 | // 5 | // Created by Håkon Bogen on 17/09/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class Forelesning8UITests: XCTestCase { 11 | 12 | override func setUpWithError() throws { 13 | // Put setup code here. This method is called before the invocation of each test method in the class. 14 | 15 | // In UI tests it is usually best to stop immediately when a failure occurs. 16 | continueAfterFailure = false 17 | 18 | // In UI tests it’s 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. 19 | } 20 | 21 | override func tearDownWithError() throws { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | @MainActor 26 | func testExample() throws { 27 | // UI tests must launch the application that they test. 28 | let app = XCUIApplication() 29 | app.launch() 30 | 31 | // Use XCTAssert and related functions to verify your tests produce the correct results. 32 | } 33 | 34 | @MainActor 35 | func testLaunchPerformance() throws { 36 | // This measures how long it takes to launch your application. 37 | measure(metrics: [XCTApplicationLaunchMetric()]) { 38 | XCUIApplication().launch() 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Forelesning_9/Forelesning_9UITests/Forelesning_9UITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Forelesning_9UITests.swift 3 | // Forelesning_9UITests 4 | // 5 | // Created by Håkon Bogen on 23/09/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class Forelesning_9UITests: XCTestCase { 11 | 12 | override func setUpWithError() throws { 13 | // Put setup code here. This method is called before the invocation of each test method in the class. 14 | 15 | // In UI tests it is usually best to stop immediately when a failure occurs. 16 | continueAfterFailure = false 17 | 18 | // In UI tests it’s 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. 19 | } 20 | 21 | override func tearDownWithError() throws { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | @MainActor 26 | func testExample() throws { 27 | // UI tests must launch the application that they test. 28 | let app = XCUIApplication() 29 | app.launch() 30 | 31 | // Use XCTAssert and related functions to verify your tests produce the correct results. 32 | } 33 | 34 | @MainActor 35 | func testLaunchPerformance() throws { 36 | // This measures how long it takes to launch your application. 37 | measure(metrics: [XCTApplicationLaunchMetric()]) { 38 | XCUIApplication().launch() 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /AnimationsDemo/AnimationsDemoUITests/AnimationsDemoUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnimationsDemoUITests.swift 3 | // AnimationsDemoUITests 4 | // 5 | // Created by Håkon Bogen on 07/10/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class AnimationsDemoUITests: XCTestCase { 11 | 12 | override func setUpWithError() throws { 13 | // Put setup code here. This method is called before the invocation of each test method in the class. 14 | 15 | // In UI tests it is usually best to stop immediately when a failure occurs. 16 | continueAfterFailure = false 17 | 18 | // In UI tests it’s 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. 19 | } 20 | 21 | override func tearDownWithError() throws { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | @MainActor 26 | func testExample() throws { 27 | // UI tests must launch the application that they test. 28 | let app = XCUIApplication() 29 | app.launch() 30 | 31 | // Use XCTAssert and related functions to verify your tests produce the correct results. 32 | } 33 | 34 | @MainActor 35 | func testLaunchPerformance() throws { 36 | // This measures how long it takes to launch your application. 37 | measure(metrics: [XCTApplicationLaunchMetric()]) { 38 | XCUIApplication().launch() 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Demo-Appstorage/Demo-AppstorageUITests/Demo_AppstorageUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Demo_AppstorageUITests.swift 3 | // Demo-AppstorageUITests 4 | // 5 | // Created by Håkon Bogen on 29/10/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class Demo_AppstorageUITests: XCTestCase { 11 | 12 | override func setUpWithError() throws { 13 | // Put setup code here. This method is called before the invocation of each test method in the class. 14 | 15 | // In UI tests it is usually best to stop immediately when a failure occurs. 16 | continueAfterFailure = false 17 | 18 | // In UI tests it’s 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. 19 | } 20 | 21 | override func tearDownWithError() throws { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | @MainActor 26 | func testExample() throws { 27 | // UI tests must launch the application that they test. 28 | let app = XCUIApplication() 29 | app.launch() 30 | 31 | // Use XCTAssert and related functions to verify your tests produce the correct results. 32 | } 33 | 34 | @MainActor 35 | func testLaunchPerformance() throws { 36 | // This measures how long it takes to launch your application. 37 | measure(metrics: [XCTApplicationLaunchMetric()]) { 38 | XCUIApplication().launch() 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /StudentRegistry/StudentRegistryUITests/StudentRegistryUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StudentRegistryUITests.swift 3 | // StudentRegistryUITests 4 | // 5 | // Created by Håkon Bogen on 15/10/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class StudentRegistryUITests: XCTestCase { 11 | 12 | override func setUpWithError() throws { 13 | // Put setup code here. This method is called before the invocation of each test method in the class. 14 | 15 | // In UI tests it is usually best to stop immediately when a failure occurs. 16 | continueAfterFailure = false 17 | 18 | // In UI tests it’s 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. 19 | } 20 | 21 | override func tearDownWithError() throws { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | @MainActor 26 | func testExample() throws { 27 | // UI tests must launch the application that they test. 28 | let app = XCUIApplication() 29 | app.launch() 30 | 31 | // Use XCTAssert and related functions to verify your tests produce the correct results. 32 | } 33 | 34 | @MainActor 35 | func testLaunchPerformance() throws { 36 | // This measures how long it takes to launch your application. 37 | measure(metrics: [XCTApplicationLaunchMetric()]) { 38 | XCUIApplication().launch() 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Forelesning3/Forelesning3/MyList.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MyList.swift 3 | // Forelesning3 4 | // 5 | // Created by Håkon Bogen on 02/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct MyList: View { 11 | 12 | let names: [String] = ["Håkon", "Mari", "Peter", "Rob", "Abdullah"] 13 | 14 | var body: some View { 15 | VStack { 16 | Text("Klasseliste") 17 | .font(.largeTitle) 18 | // List(names, id: \.self) { name in 19 | // HStack { 20 | // Image(systemName: "person") 21 | // Spacer() 22 | // Text(name) 23 | // } 24 | // } 25 | ScrollView(.vertical) { 26 | ForEach(names, id:\.self) { name in 27 | HStack { 28 | Image(systemName: "person") 29 | .padding(.leading, 15) 30 | Text("\(name)") 31 | .padding(.leading, 5) 32 | Spacer() 33 | Text("(3. året)") 34 | Spacer() 35 | .frame(width: UIScreen.main.bounds .width / 4) 36 | Text("PG5602") 37 | .padding(.trailing) 38 | } 39 | } 40 | } 41 | Spacer() 42 | } 43 | } 44 | } 45 | 46 | #Preview { 47 | MyList() 48 | } 49 | -------------------------------------------------------------------------------- /LibraryApp/LibraryApp/BookListView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // LibraryApp 4 | // 5 | // Created by Håkon Bogen on 14/10/2025. 6 | // 7 | 8 | import SwiftUI 9 | import SwiftData 10 | 11 | struct BookListView: View { 12 | 13 | @Query(sort: \Book.title) private var books: [Book] 14 | @Environment(\.modelContext) private var modelContext 15 | 16 | @State private var isShowingAddBookScreen = false 17 | 18 | func onDeleteBooks(at offsets: IndexSet) { 19 | for index in offsets { 20 | let book = books[index] 21 | modelContext.delete(book) 22 | 23 | try! modelContext.save() 24 | } 25 | } 26 | 27 | var body: some View { 28 | List { 29 | ForEach(books) { book in 30 | BookRowView(book: book) 31 | } 32 | .onDelete(perform: onDeleteBooks) 33 | } 34 | .navigationTitle("My books") 35 | .toolbar { 36 | 37 | ToolbarItem(placement: .navigationBarTrailing) { 38 | Button.init { 39 | // vis legg til bok-skjerm 40 | isShowingAddBookScreen = true 41 | } label: { 42 | Image(systemName: "plus") 43 | } 44 | 45 | } 46 | }.sheet(isPresented: $isShowingAddBookScreen) { 47 | AddBookView() 48 | } 49 | 50 | } 51 | } 52 | 53 | #Preview { 54 | NavigationView { 55 | BookListView() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /FilteringSortingExample/FilteringSortingExampleUITests/FilteringSortingExampleUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FilteringSortingExampleUITests.swift 3 | // FilteringSortingExampleUITests 4 | // 5 | // Created by Håkon Bogen on 12/11/2025. 6 | // 7 | 8 | import XCTest 9 | 10 | final class FilteringSortingExampleUITests: XCTestCase { 11 | 12 | override func setUpWithError() throws { 13 | // Put setup code here. This method is called before the invocation of each test method in the class. 14 | 15 | // In UI tests it is usually best to stop immediately when a failure occurs. 16 | continueAfterFailure = false 17 | 18 | // In UI tests it’s 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. 19 | } 20 | 21 | override func tearDownWithError() throws { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | @MainActor 26 | func testExample() throws { 27 | // UI tests must launch the application that they test. 28 | let app = XCUIApplication() 29 | app.launch() 30 | 31 | // Use XCTAssert and related functions to verify your tests produce the correct results. 32 | } 33 | 34 | @MainActor 35 | func testLaunchPerformance() throws { 36 | // This measures how long it takes to launch your application. 37 | measure(metrics: [XCTApplicationLaunchMetric()]) { 38 | XCUIApplication().launch() 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Forelesning7/Forelesning7/ProfileView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProfileView.swift 3 | // Forelesning7 4 | // 5 | // Created by Håkon Bogen on 16/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ProfileView: View { 11 | 12 | let profileURL = URL(string: "https://picsum.photos/200/200?random=profile") 13 | 14 | var body: some View { 15 | VStack { 16 | AsyncImage(url: profileURL) { image in 17 | image 18 | .resizable() 19 | .aspectRatio(contentMode: .fill) 20 | .frame(width: 120, height: 120) 21 | .clipShape(Circle()) 22 | 23 | } placeholder: { 24 | Circle() 25 | .fill(Color.gray.opacity(0.3)) 26 | .frame(width: 120, height: 120) 27 | // lag grå, samme str, med ikon inni 28 | .overlay { 29 | Image(systemName: "person.fill") 30 | .font(.system(size: 50)) 31 | .foregroundStyle(.gray) 32 | // .foregroundColor(.gray) 33 | } 34 | } // End AsyncImage 35 | 36 | VStack { 37 | Text("Ola Nordmann") 38 | .font(.title2) 39 | .fontWeight(.semibold) 40 | Text("iOS-utvikler") 41 | } 42 | } // End VStack 43 | } // End body 44 | } // End struct ProfileView 45 | 46 | #Preview { 47 | ProfileView() 48 | } 49 | -------------------------------------------------------------------------------- /StudentRegistry/StudentRegistry/AddStudentView.swift: -------------------------------------------------------------------------------- 1 | 2 | 3 | import SwiftUI 4 | import SwiftData 5 | 6 | struct AddStudentView: View { 7 | @Environment(\.dismiss) private var dismiss 8 | @Environment(\.modelContext) private var modelContext 9 | 10 | @State private var name = "" 11 | @State private var email = "" 12 | 13 | func onSaveButtonTapped() { 14 | let student = Student(name: name, email: email, enrollments: []) 15 | modelContext.insert(student) 16 | dismiss() 17 | // modelContext.save() 18 | } 19 | 20 | var body: some View { 21 | NavigationStack { 22 | Form { 23 | Section("Student details") { 24 | TextField("Name", text: $name) 25 | TextField("Email", text: $email) 26 | .keyboardType(.emailAddress) 27 | .textInputAutocapitalization(.never) 28 | 29 | } 30 | } 31 | .navigationTitle("Add Student") 32 | .toolbar { 33 | ToolbarItem(placement: .cancellationAction) { 34 | Button("Cancel") { 35 | // Hva skjer når vi kaller cancel? 36 | dismiss() 37 | } 38 | } 39 | ToolbarItem(placement: .confirmationAction) { 40 | Button("Save") { 41 | onSaveButtonTapped() 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } 48 | #Preview { 49 | AddStudentView() 50 | } 51 | 52 | -------------------------------------------------------------------------------- /Forelesning8/Forelesning8/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // Forelesning8 4 | // 5 | // Created by Håkon Bogen on 17/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | 12 | @State private var isLoading = false 13 | 14 | @State private var errorMessage: String? = nil 15 | 16 | @State private var users: [User] = [] 17 | 18 | func getUsers() async { 19 | isLoading = true 20 | errorMessage = nil 21 | 22 | do { 23 | let url = URL(string: "https://jsonplaceholder.typicode.com/users")! 24 | let (data, response) = try await URLSession.shared.data(from: url) 25 | let users = try JSONDecoder().decode([User].self, from: data) 26 | self.users = users 27 | isLoading = false 28 | 29 | } catch { 30 | errorMessage = "Noe gikk galt! \(error.localizedDescription)" 31 | isLoading = false 32 | } 33 | } 34 | 35 | var body: some View { 36 | VStack { 37 | if isLoading { 38 | ProgressView("Henter brukere") 39 | } else if let errorMessage = errorMessage { 40 | Text(errorMessage) 41 | } else { 42 | List(users) { user in 43 | Text(user.name) 44 | } 45 | } 46 | } // End VStack 47 | // .task { 48 | // await getUsers() 49 | // } 50 | .onAppear { 51 | Task { 52 | await getUsers() 53 | } 54 | } 55 | } 56 | } 57 | 58 | #Preview { 59 | ContentView() 60 | } 61 | -------------------------------------------------------------------------------- /StudentRegistry/StudentRegistry/Models.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Models.swift 3 | // StudentRegistry 4 | // 5 | // Created by Håkon Bogen on 15/10/2025. 6 | // 7 | import SwiftData 8 | import Foundation 9 | 10 | @Model 11 | class Student { 12 | var id: UUID 13 | var name: String 14 | var email: String 15 | 16 | @Relationship(deleteRule: .cascade, inverse: \Enrollment.student) 17 | var enrollments: [Enrollment] 18 | 19 | init(name: String, email: String, enrollments: [Enrollment]) { 20 | self.id = UUID() 21 | self.name = name 22 | self.email = email 23 | self.enrollments = enrollments 24 | } 25 | } 26 | 27 | @Model 28 | class Enrollment { 29 | var id: UUID 30 | var enrollmentDate: Date 31 | var grade: String? 32 | 33 | var student: Student? 34 | var course: Course? 35 | 36 | init(grade: String? = nil, student: Student? = nil, course: Course? = nil) { 37 | self.id = UUID() 38 | self.enrollmentDate = Date() 39 | self.grade = grade 40 | self.student = student 41 | self.course = course 42 | } 43 | 44 | } 45 | 46 | @Model 47 | class Course { 48 | 49 | var id: UUID 50 | var title: String 51 | var code: String 52 | var credits: Double 53 | 54 | @Relationship(deleteRule: .cascade, inverse: \Enrollment.course) 55 | var enrollments: [Enrollment] 56 | 57 | 58 | init(title: String, code: String, credits: Double, enrollments: [Enrollment]) { 59 | self.id = UUID() 60 | self.title = title 61 | self.code = code 62 | self.credits = credits 63 | self.enrollments = enrollments 64 | } 65 | 66 | } 67 | 68 | -------------------------------------------------------------------------------- /Forelesning_9/Forelesning_9/CountryRowView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CountryRowView.swift 3 | // Forelesning_9 4 | // 5 | // Created by Håkon Bogen on 23/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct CountryRowView: View { 11 | 12 | let country: Country 13 | 14 | var body: some View { 15 | HStack { 16 | AsyncImage(url: URL(string: country.flags.png)) { image in 17 | image 18 | .aspectRatio(contentMode: .fit) 19 | .frame(width: 40, height: 40) 20 | .clipped() 21 | 22 | } placeholder: { 23 | Text(country.flag) 24 | } 25 | 26 | VStack { 27 | Text(country.name.common) 28 | // Optional chaining: 29 | if let capital = country.capital?.first { 30 | Text(capital) 31 | .foregroundStyle(.secondary) 32 | } // end if let 33 | } // end vstack 34 | 35 | Spacer() 36 | VStack { 37 | Text("Innbyggere: \(country.population)") 38 | Text("Areal: \(country.area) km") 39 | } 40 | 41 | } 42 | } 43 | } 44 | 45 | #Preview { 46 | let countryName = Country.CountryName.init(common: "Norge", official: "Kongeriket Norge") 47 | 48 | let flag = Country.Flag.init(png: "", svg: "", alt: "Firkant med blå og hvite striper med rød rundt") 49 | let coatOfArms = Country.CoatOfArms(png: nil, svg: nil) 50 | 51 | let country = Country(name: countryName, region: "europe", subregion: "Skandinavia", population: 5400000, flag: "🇳🇴", flags: flag, capital: ["Oslo"], area: 350000, coatOfArms: coatOfArms) 52 | 53 | List { 54 | CountryRowView(country: country) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Swiftgen generated 6 | TEMPLATE/App/Shared/UI/Resources/L10n.swift 7 | TEMPLATE/App/Shared/UI/Resources/Assets.swift 8 | 9 | ## Build generated 10 | build/ 11 | DerivedData 12 | 13 | ## Various settings 14 | *.pbxuser 15 | !default.pbxuser 16 | *.mode1v3 17 | !default.mode1v3 18 | *.mode2v3 19 | !default.mode2v3 20 | *.perspectivev3 21 | !default.perspectivev3 22 | xcuserdata 23 | 24 | ## Other 25 | *.xccheckout 26 | *.moved-aside 27 | *.xcuserstate 28 | *.xcscmblueprint 29 | *.DS_Store 30 | 31 | ## Obj-C/Swift specific 32 | *.hmap 33 | *.ipa 34 | *.xcarchive 35 | *.app.dSYM.zip 36 | 37 | # CocoaPods 38 | # 39 | # We recommend against adding the Pods directory to your .gitignore. However 40 | # you should judge for yourself, the pros and cons are mentioned at: 41 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 42 | 43 | /Pods 44 | 45 | ##Fastlane 46 | # fastlane specific 47 | fastlane/report.xml 48 | 49 | # deliver temporary files 50 | fastlane/Preview.html 51 | 52 | # scan/snapshot temporary files (default values) 53 | /metrics 54 | /tests_derived_data 55 | /screenshots 56 | 57 | #fastlane plugins 58 | Pluginfile_fastlane 59 | Gemfile_fastlane 60 | Gemfile_fastlane.lock 61 | 62 | #fastlane build artifacts 63 | /build 64 | /derived_data 65 | /fastlane/test_output 66 | 67 | #metadata 68 | /fastlane/**/metadata/**/* 69 | /fastlane/**/screenshots/**/* 70 | 71 | ##AppCode 72 | .idea/ 73 | 74 | ##Bundle 75 | .bundle/config 76 | 77 | ##TargetEnvironment 78 | Modules/**/*Environment+current.swift 79 | BuildSettings/**/TargetEnvironment.xcconfig 80 | 81 | #Github Action 82 | .bundle/ 83 | vendor/ 84 | Packages/ 85 | ci_derived_data/ 86 | 87 | # Livekode files (teacher only) 88 | **/livekode.swift 89 | livekode/ 90 | -------------------------------------------------------------------------------- /LibraryApp/LibraryApp/AddBookView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AddBookView.swift 3 | // LibraryApp 4 | // 5 | // Created by Håkon Bogen on 14/10/2025. 6 | // 7 | 8 | import SwiftUI 9 | import SwiftData 10 | 11 | struct AddBookView: View { 12 | 13 | @Environment(\.dismiss) private var dismiss 14 | @Environment(\.modelContext) private var modelContext 15 | @State private var title = "" 16 | @State private var author = "" 17 | @State private var yearPublished = "" 18 | 19 | private var isValid: Bool { 20 | !title.isEmpty && 21 | !author.isEmpty && 22 | Int(yearPublished) != nil 23 | } 24 | 25 | func onSaveButtonTapped() { 26 | guard let year = Int(yearPublished) else { return } 27 | let newBook = Book(id: UUID(), title: title, author: author, yearpublished: year, isRead: false) 28 | modelContext.insert(newBook) 29 | dismiss() 30 | 31 | 32 | } 33 | 34 | var body: some View { 35 | NavigationStack { 36 | Form { 37 | Section("Book details") { 38 | TextField("Title", text: $title) 39 | TextField("Author", text: $author) 40 | TextField("Year published", text: $yearPublished) 41 | .keyboardType(.numberPad) 42 | } 43 | } 44 | .navigationTitle("Add book") 45 | .navigationBarTitleDisplayMode(.inline) 46 | .toolbar { 47 | ToolbarItem(placement: .cancellationAction) { 48 | Button("Cancel") { 49 | dismiss() 50 | } 51 | } 52 | ToolbarItem(placement: .confirmationAction) { 53 | Button("Save") { 54 | onSaveButtonTapped() 55 | } 56 | .disabled(!isValid) 57 | } 58 | } 59 | } 60 | Text("Hello world") 61 | } 62 | } 63 | 64 | #Preview { 65 | AddBookView() 66 | } 67 | -------------------------------------------------------------------------------- /Forelesning7/Forelesning7/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // Forelesning7 4 | // 5 | // Created by Håkon Bogen on 16/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | 12 | let photoURLs = [ 13 | "https://picsum.photos/300/200?random=1", 14 | "https://picsum.photos/200/400?random=1", 15 | "https://picsum.p/200/400?random=1" 16 | ] 17 | 18 | var body: some View { 19 | NavigationView { 20 | ScrollView { 21 | LazyVGrid(columns: [ 22 | // Hvordan er layouten? 23 | GridItem(.flexible()), 24 | GridItem(.flexible()) 25 | ]) { 26 | ForEach(0.. Void { 23 | if newTodoText.isEmpty == false { 24 | todos.append(newTodoText) 25 | newTodoText = "" 26 | } 27 | 28 | } 29 | 30 | func deleteTodo(offset: IndexSet) { 31 | print("todos before \(todos)") 32 | todos.remove(atOffsets: offset) 33 | print("todos after \(todos)") 34 | } 35 | 36 | var body: some View { 37 | NavigationView { 38 | VStack { 39 | TextField("Add todo", text: $newTodoText) 40 | 41 | Button { 42 | didTapButton() 43 | } label: { 44 | // 45 | Text("Legg til") 46 | } 47 | 48 | List { 49 | ForEach(todos, id: \.self) { todo in 50 | 51 | NavigationLink { 52 | 53 | TodoDetailView(todoItem: todo) 54 | /// TodoHelpView vises herfra 55 | 56 | /// IKKE GJØR dette 57 | // let todoDetail = TodoDetailView() 58 | // todoDetail.todoItem = todo 59 | 60 | } label: { 61 | Label(todo, systemImage: "pencil") 62 | } 63 | 64 | } 65 | .onDelete(perform: deleteTodo) 66 | } 67 | } 68 | .padding() 69 | } 70 | } 71 | } 72 | 73 | #Preview { 74 | TodoListView() 75 | } 76 | -------------------------------------------------------------------------------- /StudentRegistry/StudentRegistry/CoursesView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CoursesView.swift 3 | // StudentRegistry 4 | // 5 | // Created by Håkon Bogen on 15/10/2025. 6 | // 7 | 8 | import SwiftUI 9 | import SwiftData 10 | 11 | //func destination() -> some View { 12 | // 13 | //} 14 | 15 | struct CoursesView: View { 16 | // Hent data 17 | @Query(sort: \Course.code) private var courses: [Course] 18 | // Tilgang til databasen 19 | @Environment(\.modelContext) private var modelContext 20 | 21 | // Viser vi add course-skjermen? 22 | @State private var isShowingAddCourse = false 23 | 24 | var body: some View { 25 | // Vis data 26 | NavigationStack { 27 | List { 28 | // Gå gjennom hvert element i arrayet 29 | ForEach(courses) { course in // parameter course i closuren 30 | NavigationLink { 31 | // Hvor navigerer vi til, når vi trykker på dette elementet? 32 | Text("Course Detail view") 33 | } label: { 34 | // Hvordan ser denne knappen ut? 35 | Text(course.title) 36 | .font(.headline) 37 | } // End NavigationLink 38 | 39 | } // End ForEach 40 | } // End List 41 | .navigationTitle("Courses") 42 | .toolbar { 43 | // Knapper i toppen 44 | ToolbarItem(placement: .navigationBarTrailing) { 45 | 46 | Button { 47 | // Hva skjer når man trykker på knappen? 48 | // vis add course-skjerm 49 | isShowingAddCourse = true 50 | } label: { 51 | // Hvordan ser knappen ut? 52 | Image(systemName: "plus") 53 | } 54 | 55 | } 56 | } 57 | // Lytter på isShowingAdd Course 58 | .sheet(isPresented: $isShowingAddCourse) { 59 | // Hvilket view/skjerm skal vises når denne closure kjører? 60 | // Aka når isShowingAddCourse == true 61 | AddCourseView() 62 | // @TODO: Lag AddCourseView 63 | } 64 | } 65 | } 66 | } 67 | 68 | #Preview { 69 | CoursesView() 70 | } 71 | -------------------------------------------------------------------------------- /StateDemo/StateDemo/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // StateDemo 4 | // 5 | // Created by Håkon Bogen on 04/11/2025. 6 | // 7 | 8 | import SwiftUI 9 | import Foundation 10 | import Combine 11 | 12 | @MainActor 13 | class UserDataManager: ObservableObject { 14 | @Published var username = "Ola Nordmann" 15 | @Published var userAge = 25 16 | @Published var isLoggedIn = false 17 | 18 | func login() { 19 | isLoggedIn = true 20 | // sende til server 21 | // vise feilmelding hvis det feiler 22 | // lagre i keychain / swiftdata 23 | } 24 | 25 | func logout() { 26 | isLoggedIn = false 27 | } 28 | 29 | func updateUserInfo(name: String, age: Int ) { 30 | username = name 31 | userAge = age 32 | } 33 | } 34 | 35 | // Husk å dele opp disse i egne filer 36 | @MainActor 37 | class SettingsStore: ObservableObject { 38 | 39 | @Published var isDarkMode = false 40 | @Published var notificationsEnabled = false 41 | @Published var fontSize = 16.0 42 | 43 | } 44 | 45 | struct ContentView: View { 46 | // State for kun dette viewet 47 | @State private var counter = 0 48 | @State private var selectedTab = 0 49 | 50 | 51 | @StateObject private var settings = SettingsStore() 52 | @StateObject private var userDataManager = UserDataManager() 53 | 54 | var body: some View { 55 | NavigationView { 56 | TabView(selection: $selectedTab) { 57 | 58 | // Tab 1 59 | ScrollView { 60 | 61 | }.tabItem { 62 | Image(systemName: "1.circle") 63 | Text("@State") 64 | } 65 | .tag(0) // marker så index 0 = denne taben, hvis du setter selectedTab 66 | 67 | ScrollView { 68 | UserProfileView() 69 | LocationView() 70 | }.tabItem { 71 | Image(systemName: "2.circle") 72 | Text("Observable") 73 | } 74 | .tag(1) 75 | } 76 | .environmentObject(settings) 77 | .environmentObject(userDataManager) 78 | .navigationTitle("State Management") 79 | 80 | } 81 | .preferredColorScheme(settings.isDarkMode ? .dark : .light) 82 | 83 | } 84 | } 85 | 86 | #Preview { 87 | ContentView() 88 | } 89 | -------------------------------------------------------------------------------- /StateDemo/StateDemo/LocationView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocationView.swift 3 | // StateDemo 4 | // 5 | // Created by Håkon Bogen on 04/11/2025. 6 | // 7 | 8 | 9 | import SwiftUI 10 | import Foundation 11 | import CoreLocation 12 | import Combine 13 | 14 | class LocationViewModel: NSObject, ObservableObject, CLLocationManagerDelegate { 15 | 16 | @Published var location: CLLocation? 17 | @Published var authorizationStatus: CLAuthorizationStatus = .notDetermined 18 | @Published var locationString = "Ingen lokasjon" 19 | 20 | private let locationManager = CLLocationManager() 21 | 22 | override init() { 23 | super.init() 24 | // vi abbonnerer på events fra Apple sin Location Manager 25 | locationManager.delegate = self 26 | locationManager.desiredAccuracy = kCLLocationAccuracyBest 27 | } 28 | 29 | func requestLocation() { 30 | // Be om location events når appen er i bruk // aka er åpen 31 | locationManager.requestWhenInUseAuthorization() 32 | } 33 | 34 | func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 35 | 36 | location = locations.first 37 | if let location = locations.first { 38 | locationString = "Lat: \(String(format: "%.4f", location.coordinate.latitude)) Lon: \(String(format: "%.4f", location.coordinate.longitude))" 39 | } 40 | } 41 | func locationManager(_ manager: CLLocationManager, didFailWithError error: any Error) { 42 | print(error) 43 | } 44 | 45 | func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { 46 | 47 | authorizationStatus = status 48 | if status == .authorizedWhenInUse || status == .authorizedAlways { 49 | locationManager.startUpdatingLocation() 50 | } 51 | } 52 | 53 | 54 | } 55 | 56 | struct LocationView: View { 57 | @StateObject private var locationViewModel = LocationViewModel() 58 | 59 | var body: some View { 60 | VStack(alignment: .leading) { 61 | Text("Lokasjon") 62 | .font(.headline) 63 | Text("Status: \(locationViewModel.authorizationStatus)") 64 | Text("Lokasjon: \(locationViewModel.locationString)") 65 | Button("Be om tilgang til lokasjon") { 66 | locationViewModel.requestLocation() 67 | } 68 | .buttonStyle(.borderedProminent) 69 | } 70 | 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /plan.md: -------------------------------------------------------------------------------- 1 | # PG5602 - Oppgaver og Forelesninger 2 | 3 | ## Uke 3-4: SwiftUI Fundamentals 4 | 5 | ### Forelesning 4: SwiftUI Basics & @State ✅ 6 | - View protocol 7 | - Basic views (Text, Button, Image) 8 | - @State property wrapper 9 | - Slider, Colorpicker, andre innebygde views 10 | 11 | ### Forelesning 5: Stacks & Navigasjon 12 | - ZStack, List med navigasjon 13 | - Spacer, Divider 14 | - NavigationView, NavigationLink 15 | - Modifiers (.padding, .background, .font) 16 | - .onDelete, .onMove 17 | 18 | ### Forelesning 6: Forms & User Input 19 | - TextField 20 | - List 21 | - Form, Section 22 | - Binding ($) 23 | 24 | ## Uke 5-6: Intermediate SwiftUI 25 | 26 | 27 | ### Forelesning 7: Images & Async Loading 28 | - Image views 29 | - AsyncImage 30 | - SF Symbols 31 | - Live code: Photo gallery app 32 | 33 | ### Forelesning 8: URL & URLSession 34 | - api kall 35 | - vise data fra api 36 | - feilhåndtering 37 | 38 | ### Forelesning 9: JSON 39 | - api kall -> JSON 40 | - Serialisering av data 41 | - JSONDecoder/JSONEncoder 42 | - Codable 43 | 44 | ## Uke 7-8: Advanced UI & Animation 45 | 46 | 47 | ### Forelesning 10: Custom Views & ViewBuilder 48 | - Extracting subviews 49 | - @ViewBuilder 50 | - Custom modifiers 51 | 52 | ### Forelesning 11: Animations & Transitions 53 | - withAnimation 54 | - .animation modifier 55 | - .transition 56 | 57 | ### Forelesning 12: Gestures & Interactivity 58 | - Tap, drag, pinch gestures 59 | - @GestureState 60 | - Combining gestures 61 | 62 | ## Uke 9-10: Data & Networking 63 | 64 | ### Forelesning 13: Core Data Basics 65 | - Core Data setup 66 | - @FetchRequest 67 | - NSManagedObject 68 | 69 | ### Forelesning 14: Advanced Networking 70 | - URLSession 71 | - async/await 72 | - Error handling 73 | 74 | ### Forelesning 15: Testing & Debugging 75 | - Unit testing SwiftUI views 76 | - Debugging techniques 77 | - Performance optimization 78 | 79 | ## Uke 11-12: iOS Integration 80 | 81 | ### Forelesning 16: Device Features 82 | - Camera integration 83 | - Photo library access 84 | - Live code: Location-based photo app 85 | 86 | ### Forelesning 17: Device Features 87 | - Location services 88 | - Photo with locations 89 | - Live code: Reminder app 90 | 91 | ### Forelesning 18: More API 92 | - POST / PUT requests 93 | - Authentication 94 | - Error handling 95 | 96 | ## Uke 13-14: Advanced Topics & Projects 97 | 98 | ### Forelesning 19: App Architecture & Patterns 99 | - MVVM pattern 100 | - Dependency injection 101 | - Code organization 102 | 103 | ### Forelesning 20: App Store & Deployment 104 | - App icons, launch screens 105 | - App Store Connect 106 | - TestFlight 107 | -------------------------------------------------------------------------------- /StateDemo/StateDemo/UserProfileView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserProfileView.swift 3 | // StateDemo 4 | // 5 | // Created by Håkon Bogen on 04/11/2025. 6 | // 7 | import SwiftUI 8 | import Foundation 9 | import Combine 10 | 11 | struct UserProfileView: View { 12 | // "Globalt" objekt som brukes av flere views 13 | @EnvironmentObject var userManager: UserDataManager 14 | 15 | // Lokal state for kun dette viewet! 16 | @State private var newName = "" 17 | @State private var newAge = "" 18 | @State private var isShowingEditSheet = false 19 | 20 | var body: some View { 21 | VStack(alignment: .leading, spacing: 10) { 22 | Text("Brukerprofil") 23 | .font(.headline) 24 | .foregroundStyle(.blue) 25 | 26 | Text("Navn \(userManager.username)") 27 | Text("Alder: \(userManager.userAge)") 28 | Text("Status: \(userManager.isLoggedIn ? "Innlogget" : "Logget ut")") 29 | 30 | HStack { 31 | Button(userManager.isLoggedIn ? "Logg ut" : "Logg inn") { 32 | // Refactor dette inn i userManager? 33 | if userManager.isLoggedIn { 34 | userManager.logout() 35 | } else { 36 | userManager.login() 37 | } 38 | } 39 | .buttonStyle(.borderedProminent) 40 | Button("Rediger profil") { 41 | newName = userManager.username 42 | newAge = String(userManager.userAge) 43 | isShowingEditSheet = true 44 | } 45 | .buttonStyle(.bordered) 46 | } 47 | } 48 | .padding() 49 | .backgroundStyle(Color.gray.opacity(0.1)) 50 | .cornerRadius(8) 51 | .sheet(isPresented: $isShowingEditSheet) { 52 | // Burde være et eget View i en egen fil! 53 | NavigationView { 54 | Form { 55 | TextField("Navn", text: $newName) 56 | TextField("Alder", text: $newAge) 57 | .keyboardType(.numberPad) 58 | } 59 | .navigationTitle("Rediger profil") 60 | .navigationBarItems(leading: Button("Avbryt") { 61 | isShowingEditSheet = false 62 | }, trailing: Button("Lagre") { 63 | if let age = Int(newAge) { 64 | userManager.updateUserInfo(name: newName, age: age) 65 | } 66 | isShowingEditSheet = false 67 | }) 68 | } 69 | } 70 | 71 | } 72 | } 73 | #Preview { 74 | UserProfileView() 75 | .environmentObject(UserDataManager()) 76 | } 77 | -------------------------------------------------------------------------------- /Demo-Appstorage/Demo-Appstorage/SearchFieldDemoView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SearchFieldDemoView.swift 3 | // Demo-Appstorage 4 | // 5 | // Created by Håkon Bogen on 29/10/2025. 6 | // 7 | 8 | 9 | import SwiftUI 10 | 11 | struct SearchFieldDemoView: View { 12 | 13 | @State private var searchText = "" 14 | @State private var isSearching = false 15 | 16 | let items = ["Apple", "Banana", "Cherry", "Fig", "Grape", "Kiwi", "Lemon", "Raspberry", "Salmonberry", "Orange", "Papaya", "Watermelon", "Strawberry", "Tangerine", "Quince"] 17 | 18 | var filteredItems: [String] { 19 | // Logikk som skal filterere arrayet items basert på searchText 20 | if searchText.isEmpty { 21 | return items 22 | } else { 23 | // filterer array basert på predikat 24 | return items.filter { $0.localizedCaseInsensitiveContains(searchText) 25 | } 26 | 27 | // return items.filter { item in 28 | // return item.localizedStandardContains(searchText) 29 | // } 30 | } 31 | 32 | } 33 | 34 | var body: some View { 35 | NavigationView { 36 | VStack { 37 | List { 38 | ForEach(filteredItems, id: \.self) { item in 39 | HStack { 40 | Image(systemName: "leaf.fill") 41 | .foregroundStyle(.green) 42 | Text(item) 43 | } 44 | } 45 | } 46 | .searchable(text: $searchText, isPresented: $isSearching) 47 | .onSubmit(of: .search) { 48 | print("Searching for: \(searchText)") 49 | } 50 | 51 | TextField("Search", text: $searchText) 52 | 53 | if !searchText.isEmpty { 54 | Text("Found \(filteredItems.count) items") 55 | .padding(.bottom, 50) 56 | .foregroundStyle(.secondary) 57 | 58 | Button("Clear") { 59 | searchText = "" 60 | isSearching = false 61 | } 62 | .disabled(searchText.isEmpty) 63 | } 64 | } 65 | .navigationTitle("Fruit Search") 66 | .toolbar { 67 | ToolbarItem(placement: .navigationBarTrailing) { 68 | Button("Clear") { 69 | searchText = "" 70 | isSearching = false 71 | } 72 | .disabled(searchText.isEmpty) 73 | } 74 | } 75 | } 76 | } 77 | } 78 | 79 | #Preview { 80 | SearchFieldDemoView() 81 | } 82 | -------------------------------------------------------------------------------- /ActionsTest/ActionsTest/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // ActionsTest 4 | // 5 | // Created by Håkon Bogen on 03/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | func buttonTapped() -> Void { 11 | print("Button tapped") 12 | } 13 | 14 | struct ContentView: View { 15 | 16 | @State private var buttonText = "Was button tapped?" 17 | 18 | @State private var name = "" 19 | 20 | @State private var counter = 0 21 | 22 | @State private var selectedColor = Color.blue 23 | 24 | @State private var isShowingColorPicker = false 25 | 26 | @State private var volume: Double = 50 27 | 28 | private func didTapPlusButton() { 29 | counter += 1 30 | } 31 | 32 | private func didTapMinusButton() { 33 | counter -= 1 34 | } 35 | 36 | var body: some View { 37 | VStack { 38 | TextField("Your name", text: $name) 39 | .textFieldStyle(.roundedBorder) 40 | .font(.headline) 41 | 42 | Text(buttonText) 43 | .font(.largeTitle) 44 | 45 | Button("Logg inn") { 46 | buttonText = "Velkommen \(name)" 47 | } 48 | 49 | HStack { 50 | Button { 51 | didTapPlusButton() 52 | } label: { 53 | HStack { 54 | Image(systemName: "plus") 55 | } 56 | } 57 | 58 | Text("Counter: \(counter)") 59 | 60 | Button { 61 | didTapMinusButton() 62 | } label: { 63 | Image(systemName: "minus") 64 | } 65 | } 66 | 67 | Divider() 68 | .padding(.top) 69 | HStack { 70 | Rectangle() 71 | .fill(selectedColor) 72 | .frame(width: 50, height: 50) 73 | 74 | Button("Change color") { 75 | isShowingColorPicker = true 76 | } 77 | } 78 | Divider() 79 | .padding(.top) 80 | 81 | Circle() 82 | .fill(.red) 83 | .frame(width: CGFloat(volume), height: CGFloat(volume)) 84 | .animation(.spring(), value: volume) 85 | 86 | Text("Volume: \(Int(volume))%") 87 | 88 | Slider(value: $volume, in: 0...100) 89 | } 90 | .padding() 91 | .sheet(isPresented: $isShowingColorPicker) { 92 | Text("Pick a color") 93 | ColorPicker("Farge", selection: $selectedColor) 94 | .padding() 95 | } 96 | } 97 | } 98 | 99 | #Preview { 100 | ContentView() 101 | } 102 | -------------------------------------------------------------------------------- /StudentRegistry/StudentRegistry/AddCourseView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AddCourseView.swift 3 | // StudentRegistry 4 | // 5 | // Created by Håkon Bogen on 21/10/2025. 6 | // 7 | import SwiftUI 8 | import SwiftData 9 | 10 | // Lag View 11 | 12 | 13 | 14 | struct AddCourseView : View { 15 | // Mulighet for å lukke viewet vi er i selv 16 | @Environment(\.dismiss) private var dismiss 17 | 18 | // Tilggang til databasen 19 | @Environment(\.modelContext) private var modelContext 20 | 21 | @State private var title = "" 22 | @State private var code = "" 23 | @State private var credits = 7.5 24 | 25 | var isValid: Bool { 26 | // Hva skal denne returnere? 27 | return !title.isEmpty && !code.isEmpty 28 | } 29 | 30 | func saveCourse() { 31 | let newCourse = Course(title: title, code: code, credits: credits, enrollments: [Enrollment]()) 32 | modelContext.insert(newCourse) 33 | // Ta høyde for exceptions 34 | do { 35 | // Faktisk skriv endringer i context til disk (persistere) 36 | try modelContext.save() 37 | } catch { 38 | print(error) 39 | } 40 | 41 | dismiss() 42 | // Hvordan lagrer vi objektet i databasen? 43 | // Lukke skjermen? 44 | } 45 | 46 | var body: some View { 47 | NavigationStack { 48 | Form { 49 | TextField("Title", text: $title) 50 | TextField("Code", text: $code) 51 | .textInputAutocapitalization(.characters) 52 | 53 | Picker("Credits", selection: $credits) { 54 | ForEach([7.5, 10 , 15 ], id: \.self) { credit in 55 | Text("\(credit)") 56 | .tag(credit) // Linker "5" til 5 // String -> Int 57 | } 58 | } 59 | .navigationTitle("Add Course") 60 | .toolbar { 61 | ToolbarItem(placement: .cancellationAction) { 62 | Button("Cancel") { 63 | dismiss() 64 | } 65 | } 66 | 67 | ToolbarItem(placement: .confirmationAction) { 68 | Button("Save") { 69 | saveCourse() 70 | } 71 | .disabled(!isValid) 72 | } 73 | } 74 | } 75 | } 76 | } 77 | } 78 | 79 | #Preview { 80 | AddCourseView() 81 | } 82 | 83 | // Hva skal være View body? 84 | 85 | // Vi må kunne sette title, code og credits 86 | // Credits må kun være lov å velges som 7,5 eller 15 87 | // Bruker må kunne lagre endringene 88 | // Bruker må kunne kansellere hvis de ikke ønsker å opprette allikevel 89 | // Skal ikke være lov å lage et kurs uten å sette antall credits! Og navn, og code! 90 | // Når ferdig, lagre oppføringen i databasen, og så lukk skjermen og gå tilbake, slik at bruker ikke trykker lagre mange ganger med samme info 91 | 92 | -------------------------------------------------------------------------------- /Forelesning_9/Forelesning_9/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // Forelesning_9 4 | // 5 | // Created by Håkon Bogen on 23/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | 12 | @State private var isLoading = false 13 | @State private var countries = [Country]() 14 | @State private var errorMessage: String? 15 | @State private var selectedRegion = "europe" 16 | @State private var searchText = "" 17 | 18 | var filteredCountries: [Country] { 19 | if searchText.isEmpty { 20 | return countries 21 | } 22 | return countries 23 | .filter { country in 24 | 25 | return country.name.common.localizedCaseInsensitiveContains(searchText) 26 | 27 | } 28 | 29 | } 30 | 31 | let regions = ["europe", "asia", "africa", "oceania", "america"] 32 | 33 | var body: some View { 34 | VStack { 35 | Text("Verdens land") 36 | .wordArtStyle() 37 | MySearchBar(text: $searchText) 38 | // .wordArtStyle() 39 | 40 | Picker("Velg region", selection: $selectedRegion) { 41 | // Vis alle mulige regioner: 42 | ForEach(regions, id: \.self) { region in 43 | Text(region) 44 | 45 | } 46 | }.onChange(of: selectedRegion) { 47 | Task { 48 | await getCountries() 49 | } 50 | } 51 | // View Modifier 52 | .pickerStyle(.segmented) 53 | 54 | if isLoading { 55 | ProgressView("Henter land") 56 | } else if let errorMessage = errorMessage { 57 | Text(errorMessage) 58 | } else { 59 | 60 | List(filteredCountries) { country in 61 | CountryRowView(country: country) 62 | } 63 | 64 | } 65 | 66 | } 67 | .padding() 68 | .wordArtStyle() 69 | .onAppear { 70 | Task { 71 | await getCountries() 72 | } 73 | } 74 | } 75 | 76 | func getCountries() async { 77 | isLoading = true 78 | errorMessage = nil 79 | do { 80 | let url = URL(string: "https://restcountries.com/v3.1/region/\(selectedRegion)")! 81 | let (data, response) = try await URLSession.shared.data(from: url) 82 | let fetchedCountries = try JSONDecoder().decode([Country].self, from: data) 83 | // String(from:data, encoding: .utf8) 84 | print(String(data: data, encoding: .utf8)) 85 | countries = fetchedCountries 86 | isLoading = false 87 | 88 | 89 | } catch let error { 90 | errorMessage = "Noe feil skjedde: \(error.localizedDescription)" 91 | isLoading = false 92 | } 93 | } 94 | } 95 | 96 | #Preview { 97 | ContentView() 98 | } 99 | -------------------------------------------------------------------------------- /Demo-Appstorage/Demo-Appstorage/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // Demo-Appstorage 4 | // 5 | // Created by Håkon Bogen on 29/10/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | 12 | // Lagres mellom hver gang appen kjører, String 13 | @AppStorage("username") private var username = "" 14 | 15 | // Denne blir false, ved første gangs kjøring, ellers så henter den den lagrede verdien 16 | @AppStorage("isDarkMode") private var isDarkMode = false 17 | 18 | // Blir null ved første gangs kjøring, ellers henter den lagret data (fra plist i filsystemet til appen / aka UserDefaults) 19 | @AppStorage("favoriteNumber") private var favoriteNumber = 0 20 | 21 | // Her lagrer vi et litt mer "avansert objekt", Date. Blir satt til dagens dato første gang, ellers hentes fra persistert data, og overrides hver gang bruker endrer denne attributten 22 | @AppStorage("lastLoginDate") private var lastLoginDate = Date() 23 | 24 | private var dateFormatter: DateFormatter { 25 | /// formatere datoen når skrives ut til String 26 | let formatter = DateFormatter() 27 | formatter.dateStyle = .medium 28 | // formatter.dateFormat = "ddMM - hh:mm yyyy" 29 | return formatter 30 | } 31 | 32 | var body: some View { 33 | NavigationView { 34 | VStack(alignment: .leading, spacing: 15) { 35 | Text("Appstorage demo") 36 | .font(.largeTitle) 37 | .bold() 38 | 39 | Text("Username") 40 | TextField("Enter username", text: $username) 41 | .textFieldStyle(RoundedBorderTextFieldStyle()) 42 | 43 | HStack { 44 | Text("Dark mode") 45 | Spacer() 46 | Toggle("", isOn: $isDarkMode) 47 | } 48 | 49 | Text("Favorite number") 50 | .font(.headline) 51 | Stepper("\(favoriteNumber)", value: $favoriteNumber, in: 0...100) 52 | 53 | Text("Last login") 54 | .font(.headline) 55 | DatePicker("Select date", selection: $lastLoginDate).datePickerStyle(CompactDatePickerStyle()) 56 | 57 | Image("myimage") 58 | Image(systemName: "") 59 | HStack { 60 | Spacer() 61 | VStack() { 62 | Text("Current values:") 63 | .font(.headline) 64 | Text("Username \(username)") 65 | Text("Dark mode is \(isDarkMode ? "On" : "Off")") 66 | Text("Favorite number: \(favoriteNumber)") 67 | Text("Last login: \(lastLoginDate, formatter: dateFormatter)") 68 | } 69 | Spacer() 70 | } 71 | 72 | } 73 | .padding() 74 | } 75 | } 76 | } 77 | 78 | #Preview { 79 | ContentView() 80 | } 81 | -------------------------------------------------------------------------------- /StudentRegistry/StudentRegistry/StudentsView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // StudentRegistry 4 | // 5 | // Created by Håkon Bogen on 15/10/2025. 6 | // 7 | 8 | import SwiftUI 9 | import SwiftData 10 | 11 | struct StudentsView: View { 12 | 13 | // spørring mot databasen som er Select * from STUDENTS 14 | @Query(sort: \Student.name) private var students: [Student] 15 | // referansen til databasen vår 16 | // 3 steg 17 | // 1. -> Lag objekt Student() 18 | // 2. insert i context: modelContext.insert(student) 19 | // 3. lagre context til disk: modelContext.save() 20 | @Environment(\.modelContext) private var modelContext 21 | 22 | @State private var isShowingAddStudentsView = false 23 | 24 | private func onDeleteStudents(at offsets: IndexSet) { 25 | 26 | } 27 | 28 | var body: some View { 29 | NavigationStack { 30 | List { 31 | ForEach(students) { student in 32 | NavigationLink { 33 | // Hvor kommer man når man trykker på student? 34 | StudentDetailView(student: student) 35 | } label: { 36 | VStack(alignment: .leading) { 37 | Text(student.name) 38 | .font(.headline) 39 | 40 | Text(student.email) 41 | .font(.subheadline) 42 | .foregroundStyle(.secondary) 43 | 44 | Text("\(student.enrollments.count) kurs") 45 | .font(.caption) 46 | .foregroundStyle(.secondary) 47 | } 48 | } 49 | }.onDelete(perform: onDeleteStudents(at:)) 50 | }.toolbar { 51 | ToolbarItem(placement: .navigationBarTrailing) { 52 | Button { 53 | isShowingAddStudentsView = true 54 | } label: { 55 | Image(systemName: "plus") 56 | } 57 | 58 | } 59 | }.sheet(isPresented: $isShowingAddStudentsView) { 60 | AddStudentView() 61 | } 62 | } 63 | .padding() 64 | } 65 | } 66 | 67 | #Preview { 68 | do { 69 | let config = ModelConfiguration(isStoredInMemoryOnly: true) 70 | let container = try ModelContainer(for: 71 | Student.self, Course.self, Enrollment.self , configurations: config) 72 | let student1 = Student(name: "Håkon", email: "hakon@kristiania.no", enrollments: []) 73 | container.mainContext.insert(student1) 74 | 75 | let iOS = Course(title: "iOS Development", code: "PG5602", credits: 15, enrollments: []) 76 | container.mainContext.insert(iOS) 77 | 78 | let enrollment1 = Enrollment(student: student1, course: iOS) 79 | container.mainContext.insert(enrollment1) 80 | 81 | return StudentsView() 82 | .modelContainer(container) 83 | 84 | } catch { 85 | fatalError() 86 | 87 | } 88 | 89 | // StudentsView() 90 | } 91 | -------------------------------------------------------------------------------- /Lecture5-Forms/Lecture5-Forms/RegistrationView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // Lecture5-Forms 4 | // 5 | // Created by Håkon Bogen on 10/09/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct Country: Hashable { 11 | let name: String 12 | let flag: String 13 | 14 | static let countries = [ 15 | Country(name: "Norge", flag: "🇳🇴"), 16 | Country(name: "USA", flag: "🇺🇸"), 17 | Country(name: "Frankrike", flag: "🇫🇷") 18 | 19 | ] 20 | } 21 | 22 | struct Person { 23 | 24 | let name: String 25 | let email: String 26 | let phone: String 27 | let country: Country 28 | let age: Int 29 | let isSubscribedToNewsLetter: Bool 30 | 31 | } 32 | 33 | struct RegistrationView: View { 34 | 35 | // Personlig informasjon 36 | @State private var name = "" 37 | @State private var email = "" 38 | @State private var phone = "" 39 | 40 | // Detaljer 41 | @State private var selectedCountry = Country(name: "Norge", flag: "🇳🇴") 42 | 43 | @State private var selectedAge = 10 44 | 45 | // Innstilling 46 | @State private var isSubscribedToNewsLetter = false 47 | 48 | let countries = [ 49 | Country(name: "Norge", flag: "🇳🇴"), 50 | Country(name: "USA", flag: "🇺🇸"), 51 | Country(name: "Frankrike", flag: "🇫🇷") 52 | 53 | ] 54 | 55 | func headerContent() -> some View { 56 | TextField("Navn", text: $name) 57 | 58 | } 59 | 60 | func registerUser() { 61 | 62 | } 63 | 64 | func didTapRegisterUserButton() { 65 | let person = Person(name: name, email: email, phone: phone, country: selectedCountry, age: selectedAge, isSubscribedToNewsLetter: isSubscribedToNewsLetter) 66 | 67 | print("did tap register user: \(person)") 68 | } 69 | 70 | 71 | var body: some View { 72 | NavigationView { 73 | Form { 74 | Section(header: Text("Personlig informasjon")) { 75 | TextField("Navn", text: $name) 76 | .keyboardType(.default) 77 | 78 | TextField("E-post", text: $email) 79 | .keyboardType(.emailAddress) 80 | .textInputAutocapitalization(.never) 81 | .autocapitalization(.none) 82 | 83 | TextField("Telefon", text: $phone) 84 | .keyboardType(.phonePad) 85 | 86 | } // End Section Personlig info 87 | Section("Detaljer") { 88 | Picker("Land", selection: $selectedCountry) { 89 | ForEach(countries, id: \.self) { country in 90 | Text("\(country.flag) \(country.name)") 91 | } 92 | }.pickerStyle(.wheel) 93 | 94 | Stepper("Alder \(selectedAge)", value: $selectedAge, in: 10...120) 95 | 96 | } // End Section Detaljer 97 | Section(header: Text("Innstillinger")) { 98 | Toggle("Motta nyhetsbrev \(isSubscribedToNewsLetter)", isOn: $isSubscribedToNewsLetter) 99 | 100 | Section { 101 | Button("Registrer bruker") { 102 | registerUser() 103 | didTapRegisterUserButton() 104 | 105 | }.disabled((!name.isEmpty || !email.isEmpty) && isSubscribedToNewsLetter == true) 106 | } 107 | } 108 | } // End Form 109 | 110 | VStack { 111 | 112 | } 113 | .padding() 114 | } 115 | } 116 | } 117 | 118 | #Preview { 119 | RegistrationView() 120 | } 121 | -------------------------------------------------------------------------------- /StudentRegistry/StudentRegistry/StudentDetailView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StudentDetailView.swift 3 | // StudentRegistry 4 | // 5 | // Created by Håkon Bogen on 22/10/2025. 6 | // 7 | 8 | import SwiftUI 9 | import SwiftData 10 | 11 | 12 | struct StudentDetailView: View { 13 | 14 | let student: Student 15 | // Vis kursene til studenten 16 | @Query private var allCourses: [Course] 17 | @Environment(\.modelContext) private var modelContext 18 | 19 | @State private var isShowingEnrollCourse = false 20 | 21 | var enrolledCourses: [Course] { 22 | return student.enrollments 23 | .compactMap { $0.course } 24 | 25 | return student.enrollments 26 | .compactMap { enrollment in 27 | return enrollment.course 28 | } 29 | } 30 | 31 | var availableCourses: [Course] { 32 | // one liner 33 | let enrolledIds = Set(enrolledCourses.map { $0.id }) 34 | 35 | // map = konverter et array til en annen type array 36 | // [Student] -> [String] 37 | 38 | let idsWithDuplicates = enrolledCourses.map { course in 39 | return course.id 40 | } 41 | 42 | let enrolledIds2 = Set(idsWithDuplicates) 43 | 44 | 45 | return allCourses.filter { !enrolledIds.contains($0.id) } 46 | 47 | // filter -> filterer ut alle elementer basert på om closure returnerer true eller false 48 | return allCourses.filter { course in 49 | return !enrolledIds.contains(course.id) 50 | } 51 | 52 | // Finn alle ID fra enrolled courses 53 | // filtrer alle kurs me de IDene 54 | // [].filter { } 55 | } 56 | 57 | // init(student: Student) { 58 | // self.student = student 59 | // } 60 | 61 | var body: some View { 62 | // Liste 63 | // Seksjon 1 personalia 64 | // Seksjon 2 påmeldte kurs 65 | /// hvis grade i et kurs, vis grade, ellers vis "In progress" 66 | // Hvis tomt, skriv at studenten har ingen påmeldte kurs 67 | // Knapp + i navbar, som skal åpne "enroll to course view" 68 | // Dette viewet skal få "available courses", som studenten kan meldes på 69 | // hvis du blir ferdig fort, style views her med custom view modifiers. eks: regnbue font 70 | NavigationStack { 71 | List { 72 | Section("Student info") { 73 | LabeledContent("Name", value: student.name) 74 | LabeledContent("Email", value: student.email) 75 | } 76 | Section("Courses ") { 77 | ForEach(student.enrollments) { enrollment in 78 | if let course = enrollment.course { 79 | HStack { 80 | Text(course.title) 81 | Spacer() 82 | // if let på grade så vi kan vise at kurset er underveis 83 | Text(enrollment.grade ?? "") 84 | .foregroundStyle(.secondary) 85 | } 86 | } 87 | }.toolbar { 88 | ToolbarItem(placement: .navigationBarTrailing) { 89 | Button { 90 | isShowingEnrollCourse = true 91 | } label: { 92 | Image(systemName: "plus") 93 | } 94 | 95 | } 96 | } 97 | .sheet(isPresented: $isShowingEnrollCourse) { 98 | EnrollStudentView(student: student, availableCourses: availableCourses) 99 | } 100 | } 101 | } 102 | } 103 | } 104 | } 105 | 106 | #Preview { 107 | do { 108 | let config = ModelConfiguration(isStoredInMemoryOnly: true) 109 | let container = try ModelContainer(for: 110 | Student.self, Course.self, Enrollment.self , configurations: config) 111 | let student1 = Student(name: "Alice Johnson", email: "alice@example.com", enrollments: []) 112 | container.mainContext.insert(student1) 113 | 114 | let iOS = Course(title: "iOS Development", code: "PG5602", credits: 15, enrollments: []) 115 | container.mainContext.insert(iOS) 116 | 117 | let enrollment1 = Enrollment(grade: "A", student: student1, course: iOS) 118 | container.mainContext.insert(enrollment1) 119 | 120 | return StudentDetailView(student: student1) 121 | .modelContainer(container) 122 | 123 | } catch { 124 | fatalError() 125 | 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /MapDemo/MapDemo/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // MapDemo 4 | // 5 | // Created by Håkon Bogen on 08/10/2025. 6 | // 7 | 8 | import SwiftUI 9 | import MapKit 10 | 11 | struct PulsingPinView : View { 12 | 13 | @State private var isPulsing = false 14 | 15 | var body: some View { 16 | ZStack { 17 | Circle() 18 | .fill(.red.opacity(0.3)) 19 | .frame(width: 60, height: 60) 20 | .scaleEffect(isPulsing ? 1.2 : 1.0) 21 | .opacity(isPulsing ? 0 : 1) 22 | 23 | Circle() 24 | .fill(.red.opacity(0.5)) 25 | .frame(width: 40, height: 40) 26 | 27 | ZStack { 28 | Circle() 29 | .fill(.red) 30 | .frame(width: 30, height: 30) 31 | Image(systemName: "mappin.circle.fill") 32 | .foregroundStyle(isPulsing ? .white : .yellow) 33 | .font(isPulsing ? .caption2 : .title) 34 | } 35 | 36 | 37 | }.onAppear { 38 | withAnimation( 39 | .easeInOut(duration: 1.5) 40 | .repeatForever(autoreverses: false)) { 41 | isPulsing = true 42 | } 43 | } 44 | } 45 | } 46 | #Preview("Pulsing pin view") { 47 | PulsingPinView() 48 | } 49 | 50 | struct PlaceOfInterest: Hashable { 51 | let name: String 52 | let latitude: CLLocationDegrees 53 | let longitude: CLLocationDegrees 54 | 55 | var coordinate: CLLocationCoordinate2D { 56 | return CLLocationCoordinate2D(latitude: latitude, longitude: longitude) 57 | } 58 | } 59 | 60 | 61 | struct ContentView: View { 62 | @State private var position: MapCameraPosition = .region( 63 | 64 | MKCoordinateRegion(center: 65 | CLLocationCoordinate2D(latitude: 59.9139, longitude: 10.7522), 66 | span: 67 | MKCoordinateSpan.init(latitudeDelta: 0.02, longitudeDelta: 0.02))) 68 | 69 | @State private var isShowingSheet = false 70 | @State private var selectedPOI: PlaceOfInterest? 71 | 72 | let locations = [ 73 | (name: "Kristiania" , lat: 59.9139, lon: 10.7522) 74 | 75 | ] 76 | 77 | let locations2 = [ 78 | PlaceOfInterest(name: "Operahuset", latitude: 59.9075, longitude: 10.7539), 79 | PlaceOfInterest(name: "Kristiania", latitude: 59.9139, longitude: 10.7522) 80 | 81 | ] 82 | 83 | var body: some View { 84 | ZStack { 85 | Map(position: $position) { 86 | 87 | // Marker("Kristiania", coordinate: CLLocationCoordinate2D(latitude: 59.9139, longitude: 10.7522)) 88 | 89 | // Marker("Operahuset", coordinate: CLLocationCoordinate2D(latitude: 59.9075, longitude: 10.7539)) 90 | ForEach(locations2, id: \.self) { location in 91 | 92 | // hvis du vil ha ballongforma: 93 | // Marker(location.name, coordinate: CLLocationCoordinate2D.init(latitude: location.latitude, longitude: location.longitude)) 94 | // .tint(location.name == "Kristiania" ? .green : .red) 95 | Annotation(location.name, coordinate: location.coordinate) { 96 | Button { 97 | print(location.name) 98 | selectedPOI = location 99 | // isShowingSheet = true 100 | } label: { 101 | if selectedPOI == location { 102 | PulsingPinView() 103 | } else { 104 | ZStack { 105 | Circle() 106 | .fill(.red) 107 | .frame(width: 40) 108 | Image(systemName: "building.2") 109 | .foregroundStyle(.white) 110 | } 111 | } 112 | }.sheet(isPresented: $isShowingSheet) { 113 | 114 | if let selectedPOI = selectedPOI { 115 | Text(selectedPOI.name) 116 | } else { 117 | Text("Fant ikke lokasjonsinfo") 118 | } 119 | } 120 | } 121 | } 122 | } 123 | VStack { 124 | Spacer() 125 | 126 | Button { 127 | // Zoom inn til min pos 128 | position = .region(MKCoordinateRegion.init(center: 129 | .init(latitude: 50, longitude: 10), span: 130 | .init(latitudeDelta: 0.2, longitudeDelta: 0.2)))qq 131 | } label: { 132 | 133 | ZStack { 134 | Circle() 135 | .frame(width: 40) 136 | Image(systemName: "person") 137 | .foregroundStyle(.white) 138 | } 139 | } 140 | } 141 | 142 | } 143 | } 144 | } 145 | 146 | #Preview { 147 | ContentView() 148 | } 149 | -------------------------------------------------------------------------------- /AnimationsDemo/AnimationsDemo/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // AnimationsDemo 4 | // 5 | // Created by Håkon Bogen on 07/10/2025. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct BasicAnimationView: View { 11 | 12 | @State var isExpanded = false 13 | 14 | var body: some View { 15 | 16 | 17 | VStack { 18 | Circle() 19 | .fill(.blue) 20 | .frame(width: isExpanded ? 200 : 100) 21 | .animation(.default, value: isExpanded) 22 | 23 | Button("Animate") { 24 | isExpanded.toggle() 25 | } 26 | } 27 | } 28 | } 29 | 30 | struct AnimationTypesView: View { 31 | 32 | @State private var offset: CGFloat = 0 33 | 34 | var body: some View { 35 | VStack(spacing: 30) { 36 | Circle() 37 | .fill(.red) 38 | .frame(width: 50) 39 | .offset(x: offset) 40 | .animation(.linear(duration: 2), value: offset) 41 | 42 | Circle() 43 | .fill(.green) 44 | .frame(width: 50) 45 | .offset(x: offset) 46 | .animation(.easeInOut(duration: 1), value: offset) 47 | 48 | Circle() 49 | .fill(.blue) 50 | .frame(width: 50) 51 | .offset(x: offset) 52 | .animation(.spring(response: 0.9, dampingFraction: 0.1), value: offset) 53 | 54 | Button("Animate") { 55 | // offset = 45 56 | offset = (offset == -150) ? 150 : -150 57 | } 58 | } 59 | } 60 | } 61 | 62 | struct ExplicitAnimationView: View { 63 | 64 | @State var rotation: Double = 0 65 | @State var scale: CGFloat = 1.0 66 | 67 | var body: some View { 68 | VStack(spacing: 40) { 69 | RoundedRectangle(cornerRadius: 20) 70 | .fill(.purple) 71 | .frame(width: 100, height: 100) 72 | .rotationEffect(.degrees(rotation)) 73 | .scaleEffect(scale) 74 | 75 | Button("animate") { 76 | withAnimation(.spring(response: 0.6, dampingFraction: 0.5)) { 77 | 78 | rotation += 360 79 | scale = scale == 1.0 ? 1.5 : 1.0 80 | } 81 | // completion: { 82 | // 83 | // } 84 | } 85 | 86 | } 87 | } 88 | } 89 | 90 | struct MultiplePropertiesView: View { 91 | @State private var isAnimated = false 92 | 93 | var body: some View { 94 | VStack(spacing: 40) { 95 | RoundedRectangle(cornerRadius: isAnimated ? 50 : 10) 96 | .fill(isAnimated ? .orange : .blue) 97 | .frame(width: isAnimated ? 200 : 100, height: isAnimated ? 200 : 100) 98 | .rotationEffect(.degrees(isAnimated ? 180 : 0)) 99 | .animation(.easeInOut(duration: 1), value: isAnimated) 100 | 101 | Button("Animate") { 102 | isAnimated.toggle() 103 | } 104 | 105 | } 106 | } 107 | } 108 | 109 | struct TransitionAnimationView: View { 110 | 111 | @State private var showDetail = false 112 | 113 | var body: some View { 114 | VStack(spacing: 20) { 115 | Button("Toggle Detail") { 116 | withAnimation(.spring) { 117 | showDetail.toggle() 118 | } 119 | } 120 | 121 | if showDetail { 122 | VStack { 123 | Text("Detail view") 124 | .font(.title) 125 | Text("This appears with transition") 126 | .foregroundStyle(.secondary) 127 | } 128 | .padding() 129 | .background(.blue.opacity(0.2)) 130 | .cornerRadius(10) 131 | .transition(.scale.combined(with: .opacity)) 132 | } 133 | } 134 | } 135 | } 136 | 137 | struct GestureAnimationView: View { 138 | 139 | @State private var offset = CGSize.zero 140 | @State private var isDragging = false 141 | 142 | var body: some View { 143 | Circle() 144 | .fill(isDragging ? .green : .blue) 145 | .frame(width: 100) 146 | .offset(offset) 147 | .gesture ( 148 | 149 | DragGesture() 150 | .onChanged { value in 151 | 152 | offset = value.translation 153 | isDragging = true 154 | }.onEnded { _ in 155 | 156 | withAnimation(.spring()) { 157 | offset = .zero 158 | isDragging = false 159 | } 160 | } 161 | ) 162 | } 163 | } 164 | 165 | struct RepeatingAnimationView: View { 166 | 167 | @State private var isPulsing = false 168 | 169 | var body: some View { 170 | 171 | VStack(spacing: 40) { 172 | Circle() 173 | .fill(isPulsing ? .blue : .red) 174 | .frame(width: 101) 175 | .scaleEffect(isPulsing ? 1.3 : 1.0) 176 | .opacity(isPulsing ? 0.5 : 1.0) 177 | .animation( 178 | .easeIn(duration: 1) 179 | .repeatForever(autoreverses: true), value: isPulsing 180 | ) 181 | Button("Start animation") { 182 | // todo finn ut hvordan man stopper animasjonen! 183 | isPulsing.toggle() 184 | } 185 | 186 | 187 | } 188 | 189 | } 190 | } 191 | 192 | 193 | 194 | struct ContentView: View { 195 | var body: some View { 196 | TabView { 197 | BasicAnimationView() 198 | .tabItem { 199 | Label("Basic animation", systemImage: "person") 200 | } 201 | AnimationTypesView() 202 | .tabItem { 203 | Label("Animation types", systemImage: "football") 204 | } 205 | ExplicitAnimationView() 206 | .tabItem { 207 | Label("Explicit animation", systemImage: "square") 208 | } 209 | MultiplePropertiesView() 210 | .tabItem { Label("Multiple properties", systemImage: "basketball")} 211 | TransitionAnimationView() 212 | .tabItem { 213 | Label("Transition", systemImage: "flask") 214 | } 215 | GestureAnimationView() 216 | .tabItem { 217 | Label("Gesture", systemImage: "shoe") 218 | } 219 | 220 | RepeatingAnimationView() 221 | .tabItem { 222 | Label("Repeating", systemImage: "repeat") 223 | } 224 | } 225 | } 226 | } 227 | 228 | #Preview { 229 | ContentView() 230 | } 231 | -------------------------------------------------------------------------------- /FilteringSortingExample/FilteringSortingExample/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // FilteringSortingExample 4 | // 5 | // Created by Håkon Bogen on 12/11/2025. 6 | // 7 | 8 | import SwiftUI 9 | import CoreLocation 10 | import Combine 11 | // Location repetisjon 12 | 13 | class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate { 14 | 15 | private let locationManager = CLLocationManager() 16 | @Published var userLocation: CLLocation? 17 | // Override standard init til NSObject, sånn at kan gjøre ting når denne klassen opprettes 18 | override init() { 19 | super.init() 20 | 21 | // denne klassen (LocationManager), skal abbonnere på eventer fra CLLocationManager 22 | // eksempel eventer: brukeren sin lokasjon ble oppdatert, brukeren ga tilgang til lokasjonen sin til appen, brukeren forflyttet seg 10 meter osv... 23 | locationManager.delegate = self 24 | // Be brukeren, den som kjører appen om lov til å få disse eventene 25 | locationManager.requestWhenInUseAuthorization() 26 | } 27 | 28 | func askForPermission() { 29 | locationManager.requestWhenInUseAuthorization() 30 | } 31 | 32 | func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { 33 | userLocation = locations.last 34 | } 35 | 36 | func locationManager(_ manager: CLLocationManager, didFailWithError error: any Error) { 37 | print("Location error: \(error)") 38 | } 39 | 40 | 41 | 42 | func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { 43 | // hvis bruker ga tilgang til "when app is in use" 44 | if status == .authorizedWhenInUse { 45 | // Be om at locationmanager får oppdateringer om location 46 | locationManager.requestLocation() 47 | } 48 | } 49 | 50 | } 51 | 52 | ///////// //// 53 | struct Student: Identifiable { 54 | 55 | let id = UUID() 56 | let name: String 57 | let age: Int 58 | let grade: Double 59 | let subject: String 60 | 61 | } 62 | 63 | 64 | struct ContentView: View { 65 | 66 | @StateObject private var locationManager = LocationManager() 67 | 68 | @State private var students = [ 69 | Student(name: "Anna", age: 20, grade: 8.5, subject: "Computer science"), 70 | Student(name: "Bob", age: 22, grade: 9.1, subject: "Mathematics"), 71 | Student(name: "Frank", age: 34, grade: 5.5, subject: "Computer science") 72 | 73 | ] 74 | 75 | enum SortOption: String, CaseIterable { 76 | case name = "Name" 77 | case age = "Age" 78 | case grade = "Grade" 79 | } 80 | 81 | let subjects = ["All", "Mathematics", "Computer science", "Physics"] 82 | 83 | @State private var searchText = "" 84 | @State private var selectedSubject = "All" 85 | @State private var minimumGrade = 0.0 86 | @State private var sortOption = SortOption.name 87 | 88 | var filteredAndSortedStudents: [Student] { 89 | // lag en kopi som vi kan endre/filtrere/sortere 90 | var result = students 91 | 92 | if !searchText.isEmpty { 93 | result = result.filter { $0.name.localizedCaseInsensitiveContains(searchText)} 94 | } 95 | 96 | if selectedSubject != "All" { 97 | result = result.filter { $0.subject == selectedSubject } 98 | } 99 | 100 | result = result.filter { $0.grade >= minimumGrade } 101 | 102 | switch sortOption { 103 | case .name: 104 | result = result.sorted { $0.name < $1.name } 105 | case .age: 106 | result = result.sorted { $0.age < $1.age } 107 | case .grade: 108 | result = result.sorted { $0.grade > $1.grade } 109 | } 110 | 111 | 112 | return result 113 | } 114 | 115 | 116 | var body: some View { 117 | NavigationView { 118 | VStack { 119 | 120 | VStack(spacing: 16) { 121 | SearchBar(text: $searchText) 122 | HStack { 123 | 124 | Picker("Subject", selection: $selectedSubject) { 125 | ForEach(subjects, id: \.self) { subject in 126 | Text(subject).tag(subject) 127 | } 128 | } 129 | 130 | }.pickerStyle(MenuPickerStyle()) 131 | 132 | // Spacer() 133 | 134 | Picker("Sort by", selection: $sortOption) { 135 | ForEach(SortOption.allCases, id: \.self) { option in 136 | Text(option.rawValue).tag(option) 137 | } 138 | } 139 | 140 | VStack { 141 | Text("Minimum grade: \(minimumGrade, specifier: "%.1f")") 142 | Slider(value: $minimumGrade, in: 0...10, step: 0.1) 143 | } 144 | } 145 | .padding() 146 | .background(Color(.systemGray6)) 147 | .cornerRadius(10) 148 | 149 | List(filteredAndSortedStudents) { student in 150 | StudentRow(student: student) 151 | } 152 | .listStyle(.plain) 153 | 154 | Text("\(filteredAndSortedStudents.count)") 155 | .font(.caption) 156 | .foregroundStyle(.secondary) 157 | Button("Oppdater lokasjon") { 158 | print(locationManager.userLocation) 159 | locationManager.askForPermission() 160 | } 161 | if let userLocation = locationManager.userLocation { 162 | Text("\(userLocation)") 163 | } 164 | } 165 | 166 | .padding() 167 | } 168 | 169 | } 170 | } 171 | 172 | struct StudentRow: View { 173 | 174 | let student: Student 175 | 176 | var body: some View { 177 | VStack(alignment: .leading, spacing: 4) { 178 | HStack { 179 | Text(student.name) 180 | .font(.headline) 181 | Spacer() 182 | Text("\(student.grade, specifier: "%.1f")") 183 | .font(.title2) 184 | .fontWeight(.bold) 185 | .foregroundColor(Color.fromGrade(student.grade)) 186 | } 187 | HStack { 188 | Text("Age: \(student.age)") 189 | .font(.caption) 190 | .foregroundStyle(.secondary) 191 | Spacer() 192 | Text(student.subject) 193 | .font(.caption) 194 | .padding(.horizontal, 8) 195 | .padding(.vertical, 2) 196 | .background(Color.blue.opacity(0.1)) 197 | .cornerRadius(4) 198 | } 199 | } 200 | .padding(.vertical, 4) 201 | } 202 | 203 | 204 | } 205 | 206 | extension Color { 207 | 208 | static func fromGrade(_ grade: Double) -> Color { 209 | switch grade { 210 | case 9...: 211 | return .green 212 | case 7..<9: 213 | return .orange 214 | default: 215 | return .red 216 | } 217 | } 218 | } 219 | 220 | struct SearchBar: View { 221 | @Binding var text: String 222 | var body: some View { 223 | HStack { 224 | Image(systemName: "magnifyingglass") 225 | .foregroundStyle(.secondary) 226 | 227 | TextField("Search students...", text: $text) 228 | .textFieldStyle(.roundedBorder) 229 | } 230 | } 231 | } 232 | 233 | 234 | #Preview { 235 | ContentView() 236 | } 237 | -------------------------------------------------------------------------------- /TodoApp/TodoApp.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 77; 7 | objects = { 8 | 9 | /* Begin PBXFileReference section */ 10 | ECD8CA032E701A5900926D13 /* TodoApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TodoApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 11 | /* End PBXFileReference section */ 12 | 13 | /* Begin PBXFileSystemSynchronizedRootGroup section */ 14 | ECD8CA052E701A5900926D13 /* TodoApp */ = { 15 | isa = PBXFileSystemSynchronizedRootGroup; 16 | path = TodoApp; 17 | sourceTree = ""; 18 | }; 19 | /* End PBXFileSystemSynchronizedRootGroup section */ 20 | 21 | /* Begin PBXFrameworksBuildPhase section */ 22 | ECD8CA002E701A5900926D13 /* Frameworks */ = { 23 | isa = PBXFrameworksBuildPhase; 24 | buildActionMask = 2147483647; 25 | files = ( 26 | ); 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXFrameworksBuildPhase section */ 30 | 31 | /* Begin PBXGroup section */ 32 | ECD8C9FA2E701A5900926D13 = { 33 | isa = PBXGroup; 34 | children = ( 35 | ECD8CA052E701A5900926D13 /* TodoApp */, 36 | ECD8CA042E701A5900926D13 /* Products */, 37 | ); 38 | sourceTree = ""; 39 | }; 40 | ECD8CA042E701A5900926D13 /* Products */ = { 41 | isa = PBXGroup; 42 | children = ( 43 | ECD8CA032E701A5900926D13 /* TodoApp.app */, 44 | ); 45 | name = Products; 46 | sourceTree = ""; 47 | }; 48 | /* End PBXGroup section */ 49 | 50 | /* Begin PBXNativeTarget section */ 51 | ECD8CA022E701A5900926D13 /* TodoApp */ = { 52 | isa = PBXNativeTarget; 53 | buildConfigurationList = ECD8CA112E701A5B00926D13 /* Build configuration list for PBXNativeTarget "TodoApp" */; 54 | buildPhases = ( 55 | ECD8C9FF2E701A5900926D13 /* Sources */, 56 | ECD8CA002E701A5900926D13 /* Frameworks */, 57 | ECD8CA012E701A5900926D13 /* Resources */, 58 | ); 59 | buildRules = ( 60 | ); 61 | dependencies = ( 62 | ); 63 | fileSystemSynchronizedGroups = ( 64 | ECD8CA052E701A5900926D13 /* TodoApp */, 65 | ); 66 | name = TodoApp; 67 | packageProductDependencies = ( 68 | ); 69 | productName = TodoApp; 70 | productReference = ECD8CA032E701A5900926D13 /* TodoApp.app */; 71 | productType = "com.apple.product-type.application"; 72 | }; 73 | /* End PBXNativeTarget section */ 74 | 75 | /* Begin PBXProject section */ 76 | ECD8C9FB2E701A5900926D13 /* Project object */ = { 77 | isa = PBXProject; 78 | attributes = { 79 | BuildIndependentTargetsInParallel = 1; 80 | LastSwiftUpdateCheck = 1600; 81 | LastUpgradeCheck = 1600; 82 | TargetAttributes = { 83 | ECD8CA022E701A5900926D13 = { 84 | CreatedOnToolsVersion = 16.0; 85 | }; 86 | }; 87 | }; 88 | buildConfigurationList = ECD8C9FE2E701A5900926D13 /* Build configuration list for PBXProject "TodoApp" */; 89 | developmentRegion = en; 90 | hasScannedForEncodings = 0; 91 | knownRegions = ( 92 | en, 93 | Base, 94 | ); 95 | mainGroup = ECD8C9FA2E701A5900926D13; 96 | minimizedProjectReferenceProxies = 1; 97 | preferredProjectObjectVersion = 77; 98 | productRefGroup = ECD8CA042E701A5900926D13 /* Products */; 99 | projectDirPath = ""; 100 | projectRoot = ""; 101 | targets = ( 102 | ECD8CA022E701A5900926D13 /* TodoApp */, 103 | ); 104 | }; 105 | /* End PBXProject section */ 106 | 107 | /* Begin PBXResourcesBuildPhase section */ 108 | ECD8CA012E701A5900926D13 /* Resources */ = { 109 | isa = PBXResourcesBuildPhase; 110 | buildActionMask = 2147483647; 111 | files = ( 112 | ); 113 | runOnlyForDeploymentPostprocessing = 0; 114 | }; 115 | /* End PBXResourcesBuildPhase section */ 116 | 117 | /* Begin PBXSourcesBuildPhase section */ 118 | ECD8C9FF2E701A5900926D13 /* Sources */ = { 119 | isa = PBXSourcesBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXSourcesBuildPhase section */ 126 | 127 | /* Begin XCBuildConfiguration section */ 128 | ECD8CA0F2E701A5B00926D13 /* Debug */ = { 129 | isa = XCBuildConfiguration; 130 | buildSettings = { 131 | ALWAYS_SEARCH_USER_PATHS = NO; 132 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 133 | CLANG_ANALYZER_NONNULL = YES; 134 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 135 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 136 | CLANG_ENABLE_MODULES = YES; 137 | CLANG_ENABLE_OBJC_ARC = YES; 138 | CLANG_ENABLE_OBJC_WEAK = YES; 139 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 140 | CLANG_WARN_BOOL_CONVERSION = YES; 141 | CLANG_WARN_COMMA = YES; 142 | CLANG_WARN_CONSTANT_CONVERSION = YES; 143 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 144 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 145 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 146 | CLANG_WARN_EMPTY_BODY = YES; 147 | CLANG_WARN_ENUM_CONVERSION = YES; 148 | CLANG_WARN_INFINITE_RECURSION = YES; 149 | CLANG_WARN_INT_CONVERSION = YES; 150 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 151 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 152 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 153 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 154 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 155 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 156 | CLANG_WARN_STRICT_PROTOTYPES = YES; 157 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 158 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 159 | CLANG_WARN_UNREACHABLE_CODE = YES; 160 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 161 | COPY_PHASE_STRIP = NO; 162 | DEBUG_INFORMATION_FORMAT = dwarf; 163 | ENABLE_STRICT_OBJC_MSGSEND = YES; 164 | ENABLE_TESTABILITY = YES; 165 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 166 | GCC_C_LANGUAGE_STANDARD = gnu17; 167 | GCC_DYNAMIC_NO_PIC = NO; 168 | GCC_NO_COMMON_BLOCKS = YES; 169 | GCC_OPTIMIZATION_LEVEL = 0; 170 | GCC_PREPROCESSOR_DEFINITIONS = ( 171 | "DEBUG=1", 172 | "$(inherited)", 173 | ); 174 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 175 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 176 | GCC_WARN_UNDECLARED_SELECTOR = YES; 177 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 178 | GCC_WARN_UNUSED_FUNCTION = YES; 179 | GCC_WARN_UNUSED_VARIABLE = YES; 180 | IPHONEOS_DEPLOYMENT_TARGET = 18.0; 181 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 182 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 183 | MTL_FAST_MATH = YES; 184 | ONLY_ACTIVE_ARCH = YES; 185 | SDKROOT = iphoneos; 186 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; 187 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 188 | }; 189 | name = Debug; 190 | }; 191 | ECD8CA102E701A5B00926D13 /* Release */ = { 192 | isa = XCBuildConfiguration; 193 | buildSettings = { 194 | ALWAYS_SEARCH_USER_PATHS = NO; 195 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 196 | CLANG_ANALYZER_NONNULL = YES; 197 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 198 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 199 | CLANG_ENABLE_MODULES = YES; 200 | CLANG_ENABLE_OBJC_ARC = YES; 201 | CLANG_ENABLE_OBJC_WEAK = YES; 202 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 203 | CLANG_WARN_BOOL_CONVERSION = YES; 204 | CLANG_WARN_COMMA = YES; 205 | CLANG_WARN_CONSTANT_CONVERSION = YES; 206 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 207 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 208 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 209 | CLANG_WARN_EMPTY_BODY = YES; 210 | CLANG_WARN_ENUM_CONVERSION = YES; 211 | CLANG_WARN_INFINITE_RECURSION = YES; 212 | CLANG_WARN_INT_CONVERSION = YES; 213 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 214 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 215 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 216 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 217 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 218 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 219 | CLANG_WARN_STRICT_PROTOTYPES = YES; 220 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 221 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 222 | CLANG_WARN_UNREACHABLE_CODE = YES; 223 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 224 | COPY_PHASE_STRIP = NO; 225 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 226 | ENABLE_NS_ASSERTIONS = NO; 227 | ENABLE_STRICT_OBJC_MSGSEND = YES; 228 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 229 | GCC_C_LANGUAGE_STANDARD = gnu17; 230 | GCC_NO_COMMON_BLOCKS = YES; 231 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 232 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 233 | GCC_WARN_UNDECLARED_SELECTOR = YES; 234 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 235 | GCC_WARN_UNUSED_FUNCTION = YES; 236 | GCC_WARN_UNUSED_VARIABLE = YES; 237 | IPHONEOS_DEPLOYMENT_TARGET = 18.0; 238 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 239 | MTL_ENABLE_DEBUG_INFO = NO; 240 | MTL_FAST_MATH = YES; 241 | SDKROOT = iphoneos; 242 | SWIFT_COMPILATION_MODE = wholemodule; 243 | VALIDATE_PRODUCT = YES; 244 | }; 245 | name = Release; 246 | }; 247 | ECD8CA122E701A5B00926D13 /* Debug */ = { 248 | isa = XCBuildConfiguration; 249 | buildSettings = { 250 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 251 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 252 | CODE_SIGN_STYLE = Automatic; 253 | CURRENT_PROJECT_VERSION = 1; 254 | DEVELOPMENT_ASSET_PATHS = "\"TodoApp/Preview Content\""; 255 | ENABLE_PREVIEWS = YES; 256 | GENERATE_INFOPLIST_FILE = YES; 257 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 258 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 259 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 260 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 261 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 262 | LD_RUNPATH_SEARCH_PATHS = ( 263 | "$(inherited)", 264 | "@executable_path/Frameworks", 265 | ); 266 | MARKETING_VERSION = 1.0; 267 | PRODUCT_BUNDLE_IDENTIFIER = no.hakonbogen.TodoApp; 268 | PRODUCT_NAME = "$(TARGET_NAME)"; 269 | SWIFT_EMIT_LOC_STRINGS = YES; 270 | SWIFT_VERSION = 5.0; 271 | TARGETED_DEVICE_FAMILY = "1,2"; 272 | }; 273 | name = Debug; 274 | }; 275 | ECD8CA132E701A5B00926D13 /* Release */ = { 276 | isa = XCBuildConfiguration; 277 | buildSettings = { 278 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 279 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 280 | CODE_SIGN_STYLE = Automatic; 281 | CURRENT_PROJECT_VERSION = 1; 282 | DEVELOPMENT_ASSET_PATHS = "\"TodoApp/Preview Content\""; 283 | ENABLE_PREVIEWS = YES; 284 | GENERATE_INFOPLIST_FILE = YES; 285 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 286 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 287 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 288 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 289 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 290 | LD_RUNPATH_SEARCH_PATHS = ( 291 | "$(inherited)", 292 | "@executable_path/Frameworks", 293 | ); 294 | MARKETING_VERSION = 1.0; 295 | PRODUCT_BUNDLE_IDENTIFIER = no.hakonbogen.TodoApp; 296 | PRODUCT_NAME = "$(TARGET_NAME)"; 297 | SWIFT_EMIT_LOC_STRINGS = YES; 298 | SWIFT_VERSION = 5.0; 299 | TARGETED_DEVICE_FAMILY = "1,2"; 300 | }; 301 | name = Release; 302 | }; 303 | /* End XCBuildConfiguration section */ 304 | 305 | /* Begin XCConfigurationList section */ 306 | ECD8C9FE2E701A5900926D13 /* Build configuration list for PBXProject "TodoApp" */ = { 307 | isa = XCConfigurationList; 308 | buildConfigurations = ( 309 | ECD8CA0F2E701A5B00926D13 /* Debug */, 310 | ECD8CA102E701A5B00926D13 /* Release */, 311 | ); 312 | defaultConfigurationIsVisible = 0; 313 | defaultConfigurationName = Release; 314 | }; 315 | ECD8CA112E701A5B00926D13 /* Build configuration list for PBXNativeTarget "TodoApp" */ = { 316 | isa = XCConfigurationList; 317 | buildConfigurations = ( 318 | ECD8CA122E701A5B00926D13 /* Debug */, 319 | ECD8CA132E701A5B00926D13 /* Release */, 320 | ); 321 | defaultConfigurationIsVisible = 0; 322 | defaultConfigurationName = Release; 323 | }; 324 | /* End XCConfigurationList section */ 325 | }; 326 | rootObject = ECD8C9FB2E701A5900926D13 /* Project object */; 327 | } 328 | -------------------------------------------------------------------------------- /ActionsTest/ActionsTest.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 77; 7 | objects = { 8 | 9 | /* Begin PBXFileReference section */ 10 | EC2B13A82E68314600FAC63C /* ActionsTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ActionsTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; 11 | /* End PBXFileReference section */ 12 | 13 | /* Begin PBXFileSystemSynchronizedRootGroup section */ 14 | EC2B13AA2E68314600FAC63C /* ActionsTest */ = { 15 | isa = PBXFileSystemSynchronizedRootGroup; 16 | path = ActionsTest; 17 | sourceTree = ""; 18 | }; 19 | /* End PBXFileSystemSynchronizedRootGroup section */ 20 | 21 | /* Begin PBXFrameworksBuildPhase section */ 22 | EC2B13A52E68314600FAC63C /* Frameworks */ = { 23 | isa = PBXFrameworksBuildPhase; 24 | buildActionMask = 2147483647; 25 | files = ( 26 | ); 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXFrameworksBuildPhase section */ 30 | 31 | /* Begin PBXGroup section */ 32 | EC2B139F2E68314600FAC63C = { 33 | isa = PBXGroup; 34 | children = ( 35 | EC2B13AA2E68314600FAC63C /* ActionsTest */, 36 | EC2B13A92E68314600FAC63C /* Products */, 37 | ); 38 | sourceTree = ""; 39 | }; 40 | EC2B13A92E68314600FAC63C /* Products */ = { 41 | isa = PBXGroup; 42 | children = ( 43 | EC2B13A82E68314600FAC63C /* ActionsTest.app */, 44 | ); 45 | name = Products; 46 | sourceTree = ""; 47 | }; 48 | /* End PBXGroup section */ 49 | 50 | /* Begin PBXNativeTarget section */ 51 | EC2B13A72E68314600FAC63C /* ActionsTest */ = { 52 | isa = PBXNativeTarget; 53 | buildConfigurationList = EC2B13B62E68314800FAC63C /* Build configuration list for PBXNativeTarget "ActionsTest" */; 54 | buildPhases = ( 55 | EC2B13A42E68314600FAC63C /* Sources */, 56 | EC2B13A52E68314600FAC63C /* Frameworks */, 57 | EC2B13A62E68314600FAC63C /* Resources */, 58 | ); 59 | buildRules = ( 60 | ); 61 | dependencies = ( 62 | ); 63 | fileSystemSynchronizedGroups = ( 64 | EC2B13AA2E68314600FAC63C /* ActionsTest */, 65 | ); 66 | name = ActionsTest; 67 | packageProductDependencies = ( 68 | ); 69 | productName = ActionsTest; 70 | productReference = EC2B13A82E68314600FAC63C /* ActionsTest.app */; 71 | productType = "com.apple.product-type.application"; 72 | }; 73 | /* End PBXNativeTarget section */ 74 | 75 | /* Begin PBXProject section */ 76 | EC2B13A02E68314600FAC63C /* Project object */ = { 77 | isa = PBXProject; 78 | attributes = { 79 | BuildIndependentTargetsInParallel = 1; 80 | LastSwiftUpdateCheck = 1600; 81 | LastUpgradeCheck = 1600; 82 | TargetAttributes = { 83 | EC2B13A72E68314600FAC63C = { 84 | CreatedOnToolsVersion = 16.0; 85 | }; 86 | }; 87 | }; 88 | buildConfigurationList = EC2B13A32E68314600FAC63C /* Build configuration list for PBXProject "ActionsTest" */; 89 | developmentRegion = en; 90 | hasScannedForEncodings = 0; 91 | knownRegions = ( 92 | en, 93 | Base, 94 | ); 95 | mainGroup = EC2B139F2E68314600FAC63C; 96 | minimizedProjectReferenceProxies = 1; 97 | preferredProjectObjectVersion = 77; 98 | productRefGroup = EC2B13A92E68314600FAC63C /* Products */; 99 | projectDirPath = ""; 100 | projectRoot = ""; 101 | targets = ( 102 | EC2B13A72E68314600FAC63C /* ActionsTest */, 103 | ); 104 | }; 105 | /* End PBXProject section */ 106 | 107 | /* Begin PBXResourcesBuildPhase section */ 108 | EC2B13A62E68314600FAC63C /* Resources */ = { 109 | isa = PBXResourcesBuildPhase; 110 | buildActionMask = 2147483647; 111 | files = ( 112 | ); 113 | runOnlyForDeploymentPostprocessing = 0; 114 | }; 115 | /* End PBXResourcesBuildPhase section */ 116 | 117 | /* Begin PBXSourcesBuildPhase section */ 118 | EC2B13A42E68314600FAC63C /* Sources */ = { 119 | isa = PBXSourcesBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXSourcesBuildPhase section */ 126 | 127 | /* Begin XCBuildConfiguration section */ 128 | EC2B13B42E68314800FAC63C /* Debug */ = { 129 | isa = XCBuildConfiguration; 130 | buildSettings = { 131 | ALWAYS_SEARCH_USER_PATHS = NO; 132 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 133 | CLANG_ANALYZER_NONNULL = YES; 134 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 135 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 136 | CLANG_ENABLE_MODULES = YES; 137 | CLANG_ENABLE_OBJC_ARC = YES; 138 | CLANG_ENABLE_OBJC_WEAK = YES; 139 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 140 | CLANG_WARN_BOOL_CONVERSION = YES; 141 | CLANG_WARN_COMMA = YES; 142 | CLANG_WARN_CONSTANT_CONVERSION = YES; 143 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 144 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 145 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 146 | CLANG_WARN_EMPTY_BODY = YES; 147 | CLANG_WARN_ENUM_CONVERSION = YES; 148 | CLANG_WARN_INFINITE_RECURSION = YES; 149 | CLANG_WARN_INT_CONVERSION = YES; 150 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 151 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 152 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 153 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 154 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 155 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 156 | CLANG_WARN_STRICT_PROTOTYPES = YES; 157 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 158 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 159 | CLANG_WARN_UNREACHABLE_CODE = YES; 160 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 161 | COPY_PHASE_STRIP = NO; 162 | DEBUG_INFORMATION_FORMAT = dwarf; 163 | ENABLE_STRICT_OBJC_MSGSEND = YES; 164 | ENABLE_TESTABILITY = YES; 165 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 166 | GCC_C_LANGUAGE_STANDARD = gnu17; 167 | GCC_DYNAMIC_NO_PIC = NO; 168 | GCC_NO_COMMON_BLOCKS = YES; 169 | GCC_OPTIMIZATION_LEVEL = 0; 170 | GCC_PREPROCESSOR_DEFINITIONS = ( 171 | "DEBUG=1", 172 | "$(inherited)", 173 | ); 174 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 175 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 176 | GCC_WARN_UNDECLARED_SELECTOR = YES; 177 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 178 | GCC_WARN_UNUSED_FUNCTION = YES; 179 | GCC_WARN_UNUSED_VARIABLE = YES; 180 | IPHONEOS_DEPLOYMENT_TARGET = 18.0; 181 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 182 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 183 | MTL_FAST_MATH = YES; 184 | ONLY_ACTIVE_ARCH = YES; 185 | SDKROOT = iphoneos; 186 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; 187 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 188 | }; 189 | name = Debug; 190 | }; 191 | EC2B13B52E68314800FAC63C /* Release */ = { 192 | isa = XCBuildConfiguration; 193 | buildSettings = { 194 | ALWAYS_SEARCH_USER_PATHS = NO; 195 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 196 | CLANG_ANALYZER_NONNULL = YES; 197 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 198 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 199 | CLANG_ENABLE_MODULES = YES; 200 | CLANG_ENABLE_OBJC_ARC = YES; 201 | CLANG_ENABLE_OBJC_WEAK = YES; 202 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 203 | CLANG_WARN_BOOL_CONVERSION = YES; 204 | CLANG_WARN_COMMA = YES; 205 | CLANG_WARN_CONSTANT_CONVERSION = YES; 206 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 207 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 208 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 209 | CLANG_WARN_EMPTY_BODY = YES; 210 | CLANG_WARN_ENUM_CONVERSION = YES; 211 | CLANG_WARN_INFINITE_RECURSION = YES; 212 | CLANG_WARN_INT_CONVERSION = YES; 213 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 214 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 215 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 216 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 217 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 218 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 219 | CLANG_WARN_STRICT_PROTOTYPES = YES; 220 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 221 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 222 | CLANG_WARN_UNREACHABLE_CODE = YES; 223 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 224 | COPY_PHASE_STRIP = NO; 225 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 226 | ENABLE_NS_ASSERTIONS = NO; 227 | ENABLE_STRICT_OBJC_MSGSEND = YES; 228 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 229 | GCC_C_LANGUAGE_STANDARD = gnu17; 230 | GCC_NO_COMMON_BLOCKS = YES; 231 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 232 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 233 | GCC_WARN_UNDECLARED_SELECTOR = YES; 234 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 235 | GCC_WARN_UNUSED_FUNCTION = YES; 236 | GCC_WARN_UNUSED_VARIABLE = YES; 237 | IPHONEOS_DEPLOYMENT_TARGET = 18.0; 238 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 239 | MTL_ENABLE_DEBUG_INFO = NO; 240 | MTL_FAST_MATH = YES; 241 | SDKROOT = iphoneos; 242 | SWIFT_COMPILATION_MODE = wholemodule; 243 | VALIDATE_PRODUCT = YES; 244 | }; 245 | name = Release; 246 | }; 247 | EC2B13B72E68314800FAC63C /* Debug */ = { 248 | isa = XCBuildConfiguration; 249 | buildSettings = { 250 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 251 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 252 | CODE_SIGN_STYLE = Automatic; 253 | CURRENT_PROJECT_VERSION = 1; 254 | DEVELOPMENT_ASSET_PATHS = "\"ActionsTest/Preview Content\""; 255 | ENABLE_PREVIEWS = YES; 256 | GENERATE_INFOPLIST_FILE = YES; 257 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 258 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 259 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 260 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 261 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 262 | LD_RUNPATH_SEARCH_PATHS = ( 263 | "$(inherited)", 264 | "@executable_path/Frameworks", 265 | ); 266 | MARKETING_VERSION = 1.0; 267 | PRODUCT_BUNDLE_IDENTIFIER = no.hakonbogen.ActionsTest; 268 | PRODUCT_NAME = "$(TARGET_NAME)"; 269 | SWIFT_EMIT_LOC_STRINGS = YES; 270 | SWIFT_VERSION = 5.0; 271 | TARGETED_DEVICE_FAMILY = "1,2"; 272 | }; 273 | name = Debug; 274 | }; 275 | EC2B13B82E68314800FAC63C /* Release */ = { 276 | isa = XCBuildConfiguration; 277 | buildSettings = { 278 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 279 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 280 | CODE_SIGN_STYLE = Automatic; 281 | CURRENT_PROJECT_VERSION = 1; 282 | DEVELOPMENT_ASSET_PATHS = "\"ActionsTest/Preview Content\""; 283 | ENABLE_PREVIEWS = YES; 284 | GENERATE_INFOPLIST_FILE = YES; 285 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 286 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 287 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 288 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 289 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 290 | LD_RUNPATH_SEARCH_PATHS = ( 291 | "$(inherited)", 292 | "@executable_path/Frameworks", 293 | ); 294 | MARKETING_VERSION = 1.0; 295 | PRODUCT_BUNDLE_IDENTIFIER = no.hakonbogen.ActionsTest; 296 | PRODUCT_NAME = "$(TARGET_NAME)"; 297 | SWIFT_EMIT_LOC_STRINGS = YES; 298 | SWIFT_VERSION = 5.0; 299 | TARGETED_DEVICE_FAMILY = "1,2"; 300 | }; 301 | name = Release; 302 | }; 303 | /* End XCBuildConfiguration section */ 304 | 305 | /* Begin XCConfigurationList section */ 306 | EC2B13A32E68314600FAC63C /* Build configuration list for PBXProject "ActionsTest" */ = { 307 | isa = XCConfigurationList; 308 | buildConfigurations = ( 309 | EC2B13B42E68314800FAC63C /* Debug */, 310 | EC2B13B52E68314800FAC63C /* Release */, 311 | ); 312 | defaultConfigurationIsVisible = 0; 313 | defaultConfigurationName = Release; 314 | }; 315 | EC2B13B62E68314800FAC63C /* Build configuration list for PBXNativeTarget "ActionsTest" */ = { 316 | isa = XCConfigurationList; 317 | buildConfigurations = ( 318 | EC2B13B72E68314800FAC63C /* Debug */, 319 | EC2B13B82E68314800FAC63C /* Release */, 320 | ); 321 | defaultConfigurationIsVisible = 0; 322 | defaultConfigurationName = Release; 323 | }; 324 | /* End XCConfigurationList section */ 325 | }; 326 | rootObject = EC2B13A02E68314600FAC63C /* Project object */; 327 | } 328 | -------------------------------------------------------------------------------- /Forelesning3/Forelesning3.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 77; 7 | objects = { 8 | 9 | /* Begin PBXFileReference section */ 10 | EC97DFF22E66D23F005E11C2 /* Forelesning3.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Forelesning3.app; sourceTree = BUILT_PRODUCTS_DIR; }; 11 | /* End PBXFileReference section */ 12 | 13 | /* Begin PBXFileSystemSynchronizedRootGroup section */ 14 | EC97DFF42E66D23F005E11C2 /* Forelesning3 */ = { 15 | isa = PBXFileSystemSynchronizedRootGroup; 16 | path = Forelesning3; 17 | sourceTree = ""; 18 | }; 19 | /* End PBXFileSystemSynchronizedRootGroup section */ 20 | 21 | /* Begin PBXFrameworksBuildPhase section */ 22 | EC97DFEF2E66D23F005E11C2 /* Frameworks */ = { 23 | isa = PBXFrameworksBuildPhase; 24 | buildActionMask = 2147483647; 25 | files = ( 26 | ); 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXFrameworksBuildPhase section */ 30 | 31 | /* Begin PBXGroup section */ 32 | EC97DFE92E66D23F005E11C2 = { 33 | isa = PBXGroup; 34 | children = ( 35 | EC97DFF42E66D23F005E11C2 /* Forelesning3 */, 36 | EC97DFF32E66D23F005E11C2 /* Products */, 37 | ); 38 | sourceTree = ""; 39 | }; 40 | EC97DFF32E66D23F005E11C2 /* Products */ = { 41 | isa = PBXGroup; 42 | children = ( 43 | EC97DFF22E66D23F005E11C2 /* Forelesning3.app */, 44 | ); 45 | name = Products; 46 | sourceTree = ""; 47 | }; 48 | /* End PBXGroup section */ 49 | 50 | /* Begin PBXNativeTarget section */ 51 | EC97DFF12E66D23F005E11C2 /* Forelesning3 */ = { 52 | isa = PBXNativeTarget; 53 | buildConfigurationList = EC97E0002E66D242005E11C2 /* Build configuration list for PBXNativeTarget "Forelesning3" */; 54 | buildPhases = ( 55 | EC97DFEE2E66D23F005E11C2 /* Sources */, 56 | EC97DFEF2E66D23F005E11C2 /* Frameworks */, 57 | EC97DFF02E66D23F005E11C2 /* Resources */, 58 | ); 59 | buildRules = ( 60 | ); 61 | dependencies = ( 62 | ); 63 | fileSystemSynchronizedGroups = ( 64 | EC97DFF42E66D23F005E11C2 /* Forelesning3 */, 65 | ); 66 | name = Forelesning3; 67 | packageProductDependencies = ( 68 | ); 69 | productName = Forelesning3; 70 | productReference = EC97DFF22E66D23F005E11C2 /* Forelesning3.app */; 71 | productType = "com.apple.product-type.application"; 72 | }; 73 | /* End PBXNativeTarget section */ 74 | 75 | /* Begin PBXProject section */ 76 | EC97DFEA2E66D23F005E11C2 /* Project object */ = { 77 | isa = PBXProject; 78 | attributes = { 79 | BuildIndependentTargetsInParallel = 1; 80 | LastSwiftUpdateCheck = 1600; 81 | LastUpgradeCheck = 1600; 82 | TargetAttributes = { 83 | EC97DFF12E66D23F005E11C2 = { 84 | CreatedOnToolsVersion = 16.0; 85 | }; 86 | }; 87 | }; 88 | buildConfigurationList = EC97DFED2E66D23F005E11C2 /* Build configuration list for PBXProject "Forelesning3" */; 89 | developmentRegion = en; 90 | hasScannedForEncodings = 0; 91 | knownRegions = ( 92 | en, 93 | Base, 94 | ); 95 | mainGroup = EC97DFE92E66D23F005E11C2; 96 | minimizedProjectReferenceProxies = 1; 97 | preferredProjectObjectVersion = 77; 98 | productRefGroup = EC97DFF32E66D23F005E11C2 /* Products */; 99 | projectDirPath = ""; 100 | projectRoot = ""; 101 | targets = ( 102 | EC97DFF12E66D23F005E11C2 /* Forelesning3 */, 103 | ); 104 | }; 105 | /* End PBXProject section */ 106 | 107 | /* Begin PBXResourcesBuildPhase section */ 108 | EC97DFF02E66D23F005E11C2 /* Resources */ = { 109 | isa = PBXResourcesBuildPhase; 110 | buildActionMask = 2147483647; 111 | files = ( 112 | ); 113 | runOnlyForDeploymentPostprocessing = 0; 114 | }; 115 | /* End PBXResourcesBuildPhase section */ 116 | 117 | /* Begin PBXSourcesBuildPhase section */ 118 | EC97DFEE2E66D23F005E11C2 /* Sources */ = { 119 | isa = PBXSourcesBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXSourcesBuildPhase section */ 126 | 127 | /* Begin XCBuildConfiguration section */ 128 | EC97DFFE2E66D242005E11C2 /* Debug */ = { 129 | isa = XCBuildConfiguration; 130 | buildSettings = { 131 | ALWAYS_SEARCH_USER_PATHS = NO; 132 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 133 | CLANG_ANALYZER_NONNULL = YES; 134 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 135 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 136 | CLANG_ENABLE_MODULES = YES; 137 | CLANG_ENABLE_OBJC_ARC = YES; 138 | CLANG_ENABLE_OBJC_WEAK = YES; 139 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 140 | CLANG_WARN_BOOL_CONVERSION = YES; 141 | CLANG_WARN_COMMA = YES; 142 | CLANG_WARN_CONSTANT_CONVERSION = YES; 143 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 144 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 145 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 146 | CLANG_WARN_EMPTY_BODY = YES; 147 | CLANG_WARN_ENUM_CONVERSION = YES; 148 | CLANG_WARN_INFINITE_RECURSION = YES; 149 | CLANG_WARN_INT_CONVERSION = YES; 150 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 151 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 152 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 153 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 154 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 155 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 156 | CLANG_WARN_STRICT_PROTOTYPES = YES; 157 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 158 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 159 | CLANG_WARN_UNREACHABLE_CODE = YES; 160 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 161 | COPY_PHASE_STRIP = NO; 162 | DEBUG_INFORMATION_FORMAT = dwarf; 163 | ENABLE_STRICT_OBJC_MSGSEND = YES; 164 | ENABLE_TESTABILITY = YES; 165 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 166 | GCC_C_LANGUAGE_STANDARD = gnu17; 167 | GCC_DYNAMIC_NO_PIC = NO; 168 | GCC_NO_COMMON_BLOCKS = YES; 169 | GCC_OPTIMIZATION_LEVEL = 0; 170 | GCC_PREPROCESSOR_DEFINITIONS = ( 171 | "DEBUG=1", 172 | "$(inherited)", 173 | ); 174 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 175 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 176 | GCC_WARN_UNDECLARED_SELECTOR = YES; 177 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 178 | GCC_WARN_UNUSED_FUNCTION = YES; 179 | GCC_WARN_UNUSED_VARIABLE = YES; 180 | IPHONEOS_DEPLOYMENT_TARGET = 18.0; 181 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 182 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 183 | MTL_FAST_MATH = YES; 184 | ONLY_ACTIVE_ARCH = YES; 185 | SDKROOT = iphoneos; 186 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; 187 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 188 | }; 189 | name = Debug; 190 | }; 191 | EC97DFFF2E66D242005E11C2 /* Release */ = { 192 | isa = XCBuildConfiguration; 193 | buildSettings = { 194 | ALWAYS_SEARCH_USER_PATHS = NO; 195 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 196 | CLANG_ANALYZER_NONNULL = YES; 197 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 198 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 199 | CLANG_ENABLE_MODULES = YES; 200 | CLANG_ENABLE_OBJC_ARC = YES; 201 | CLANG_ENABLE_OBJC_WEAK = YES; 202 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 203 | CLANG_WARN_BOOL_CONVERSION = YES; 204 | CLANG_WARN_COMMA = YES; 205 | CLANG_WARN_CONSTANT_CONVERSION = YES; 206 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 207 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 208 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 209 | CLANG_WARN_EMPTY_BODY = YES; 210 | CLANG_WARN_ENUM_CONVERSION = YES; 211 | CLANG_WARN_INFINITE_RECURSION = YES; 212 | CLANG_WARN_INT_CONVERSION = YES; 213 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 214 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 215 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 216 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 217 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 218 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 219 | CLANG_WARN_STRICT_PROTOTYPES = YES; 220 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 221 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 222 | CLANG_WARN_UNREACHABLE_CODE = YES; 223 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 224 | COPY_PHASE_STRIP = NO; 225 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 226 | ENABLE_NS_ASSERTIONS = NO; 227 | ENABLE_STRICT_OBJC_MSGSEND = YES; 228 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 229 | GCC_C_LANGUAGE_STANDARD = gnu17; 230 | GCC_NO_COMMON_BLOCKS = YES; 231 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 232 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 233 | GCC_WARN_UNDECLARED_SELECTOR = YES; 234 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 235 | GCC_WARN_UNUSED_FUNCTION = YES; 236 | GCC_WARN_UNUSED_VARIABLE = YES; 237 | IPHONEOS_DEPLOYMENT_TARGET = 18.0; 238 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 239 | MTL_ENABLE_DEBUG_INFO = NO; 240 | MTL_FAST_MATH = YES; 241 | SDKROOT = iphoneos; 242 | SWIFT_COMPILATION_MODE = wholemodule; 243 | VALIDATE_PRODUCT = YES; 244 | }; 245 | name = Release; 246 | }; 247 | EC97E0012E66D242005E11C2 /* Debug */ = { 248 | isa = XCBuildConfiguration; 249 | buildSettings = { 250 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 251 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 252 | CODE_SIGN_STYLE = Automatic; 253 | CURRENT_PROJECT_VERSION = 1; 254 | DEVELOPMENT_ASSET_PATHS = "\"Forelesning3/Preview Content\""; 255 | ENABLE_PREVIEWS = YES; 256 | GENERATE_INFOPLIST_FILE = YES; 257 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 258 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 259 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 260 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 261 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 262 | LD_RUNPATH_SEARCH_PATHS = ( 263 | "$(inherited)", 264 | "@executable_path/Frameworks", 265 | ); 266 | MARKETING_VERSION = 1.0; 267 | PRODUCT_BUNDLE_IDENTIFIER = no.hakonbogen.Forelesning3; 268 | PRODUCT_NAME = "$(TARGET_NAME)"; 269 | SWIFT_EMIT_LOC_STRINGS = YES; 270 | SWIFT_VERSION = 5.0; 271 | TARGETED_DEVICE_FAMILY = "1,2"; 272 | }; 273 | name = Debug; 274 | }; 275 | EC97E0022E66D242005E11C2 /* Release */ = { 276 | isa = XCBuildConfiguration; 277 | buildSettings = { 278 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 279 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 280 | CODE_SIGN_STYLE = Automatic; 281 | CURRENT_PROJECT_VERSION = 1; 282 | DEVELOPMENT_ASSET_PATHS = "\"Forelesning3/Preview Content\""; 283 | ENABLE_PREVIEWS = YES; 284 | GENERATE_INFOPLIST_FILE = YES; 285 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 286 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 287 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 288 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 289 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 290 | LD_RUNPATH_SEARCH_PATHS = ( 291 | "$(inherited)", 292 | "@executable_path/Frameworks", 293 | ); 294 | MARKETING_VERSION = 1.0; 295 | PRODUCT_BUNDLE_IDENTIFIER = no.hakonbogen.Forelesning3; 296 | PRODUCT_NAME = "$(TARGET_NAME)"; 297 | SWIFT_EMIT_LOC_STRINGS = YES; 298 | SWIFT_VERSION = 5.0; 299 | TARGETED_DEVICE_FAMILY = "1,2"; 300 | }; 301 | name = Release; 302 | }; 303 | /* End XCBuildConfiguration section */ 304 | 305 | /* Begin XCConfigurationList section */ 306 | EC97DFED2E66D23F005E11C2 /* Build configuration list for PBXProject "Forelesning3" */ = { 307 | isa = XCConfigurationList; 308 | buildConfigurations = ( 309 | EC97DFFE2E66D242005E11C2 /* Debug */, 310 | EC97DFFF2E66D242005E11C2 /* Release */, 311 | ); 312 | defaultConfigurationIsVisible = 0; 313 | defaultConfigurationName = Release; 314 | }; 315 | EC97E0002E66D242005E11C2 /* Build configuration list for PBXNativeTarget "Forelesning3" */ = { 316 | isa = XCConfigurationList; 317 | buildConfigurations = ( 318 | EC97E0012E66D242005E11C2 /* Debug */, 319 | EC97E0022E66D242005E11C2 /* Release */, 320 | ); 321 | defaultConfigurationIsVisible = 0; 322 | defaultConfigurationName = Release; 323 | }; 324 | /* End XCConfigurationList section */ 325 | }; 326 | rootObject = EC97DFEA2E66D23F005E11C2 /* Project object */; 327 | } 328 | -------------------------------------------------------------------------------- /Lecture5-Forms/Lecture5-Forms.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 77; 7 | objects = { 8 | 9 | /* Begin PBXFileReference section */ 10 | ECD8CAAB2E716C1B00926D13 /* Lecture5-Forms.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Lecture5-Forms.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 11 | /* End PBXFileReference section */ 12 | 13 | /* Begin PBXFileSystemSynchronizedRootGroup section */ 14 | ECD8CAAD2E716C1B00926D13 /* Lecture5-Forms */ = { 15 | isa = PBXFileSystemSynchronizedRootGroup; 16 | path = "Lecture5-Forms"; 17 | sourceTree = ""; 18 | }; 19 | /* End PBXFileSystemSynchronizedRootGroup section */ 20 | 21 | /* Begin PBXFrameworksBuildPhase section */ 22 | ECD8CAA82E716C1B00926D13 /* Frameworks */ = { 23 | isa = PBXFrameworksBuildPhase; 24 | buildActionMask = 2147483647; 25 | files = ( 26 | ); 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXFrameworksBuildPhase section */ 30 | 31 | /* Begin PBXGroup section */ 32 | ECD8CAA22E716C1B00926D13 = { 33 | isa = PBXGroup; 34 | children = ( 35 | ECD8CAAD2E716C1B00926D13 /* Lecture5-Forms */, 36 | ECD8CAAC2E716C1B00926D13 /* Products */, 37 | ); 38 | sourceTree = ""; 39 | }; 40 | ECD8CAAC2E716C1B00926D13 /* Products */ = { 41 | isa = PBXGroup; 42 | children = ( 43 | ECD8CAAB2E716C1B00926D13 /* Lecture5-Forms.app */, 44 | ); 45 | name = Products; 46 | sourceTree = ""; 47 | }; 48 | /* End PBXGroup section */ 49 | 50 | /* Begin PBXNativeTarget section */ 51 | ECD8CAAA2E716C1B00926D13 /* Lecture5-Forms */ = { 52 | isa = PBXNativeTarget; 53 | buildConfigurationList = ECD8CAB92E716C1D00926D13 /* Build configuration list for PBXNativeTarget "Lecture5-Forms" */; 54 | buildPhases = ( 55 | ECD8CAA72E716C1B00926D13 /* Sources */, 56 | ECD8CAA82E716C1B00926D13 /* Frameworks */, 57 | ECD8CAA92E716C1B00926D13 /* Resources */, 58 | ); 59 | buildRules = ( 60 | ); 61 | dependencies = ( 62 | ); 63 | fileSystemSynchronizedGroups = ( 64 | ECD8CAAD2E716C1B00926D13 /* Lecture5-Forms */, 65 | ); 66 | name = "Lecture5-Forms"; 67 | packageProductDependencies = ( 68 | ); 69 | productName = "Lecture5-Forms"; 70 | productReference = ECD8CAAB2E716C1B00926D13 /* Lecture5-Forms.app */; 71 | productType = "com.apple.product-type.application"; 72 | }; 73 | /* End PBXNativeTarget section */ 74 | 75 | /* Begin PBXProject section */ 76 | ECD8CAA32E716C1B00926D13 /* Project object */ = { 77 | isa = PBXProject; 78 | attributes = { 79 | BuildIndependentTargetsInParallel = 1; 80 | LastSwiftUpdateCheck = 1600; 81 | LastUpgradeCheck = 1600; 82 | TargetAttributes = { 83 | ECD8CAAA2E716C1B00926D13 = { 84 | CreatedOnToolsVersion = 16.0; 85 | }; 86 | }; 87 | }; 88 | buildConfigurationList = ECD8CAA62E716C1B00926D13 /* Build configuration list for PBXProject "Lecture5-Forms" */; 89 | developmentRegion = en; 90 | hasScannedForEncodings = 0; 91 | knownRegions = ( 92 | en, 93 | Base, 94 | ); 95 | mainGroup = ECD8CAA22E716C1B00926D13; 96 | minimizedProjectReferenceProxies = 1; 97 | preferredProjectObjectVersion = 77; 98 | productRefGroup = ECD8CAAC2E716C1B00926D13 /* Products */; 99 | projectDirPath = ""; 100 | projectRoot = ""; 101 | targets = ( 102 | ECD8CAAA2E716C1B00926D13 /* Lecture5-Forms */, 103 | ); 104 | }; 105 | /* End PBXProject section */ 106 | 107 | /* Begin PBXResourcesBuildPhase section */ 108 | ECD8CAA92E716C1B00926D13 /* Resources */ = { 109 | isa = PBXResourcesBuildPhase; 110 | buildActionMask = 2147483647; 111 | files = ( 112 | ); 113 | runOnlyForDeploymentPostprocessing = 0; 114 | }; 115 | /* End PBXResourcesBuildPhase section */ 116 | 117 | /* Begin PBXSourcesBuildPhase section */ 118 | ECD8CAA72E716C1B00926D13 /* Sources */ = { 119 | isa = PBXSourcesBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXSourcesBuildPhase section */ 126 | 127 | /* Begin XCBuildConfiguration section */ 128 | ECD8CAB72E716C1D00926D13 /* Debug */ = { 129 | isa = XCBuildConfiguration; 130 | buildSettings = { 131 | ALWAYS_SEARCH_USER_PATHS = NO; 132 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 133 | CLANG_ANALYZER_NONNULL = YES; 134 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 135 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 136 | CLANG_ENABLE_MODULES = YES; 137 | CLANG_ENABLE_OBJC_ARC = YES; 138 | CLANG_ENABLE_OBJC_WEAK = YES; 139 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 140 | CLANG_WARN_BOOL_CONVERSION = YES; 141 | CLANG_WARN_COMMA = YES; 142 | CLANG_WARN_CONSTANT_CONVERSION = YES; 143 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 144 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 145 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 146 | CLANG_WARN_EMPTY_BODY = YES; 147 | CLANG_WARN_ENUM_CONVERSION = YES; 148 | CLANG_WARN_INFINITE_RECURSION = YES; 149 | CLANG_WARN_INT_CONVERSION = YES; 150 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 151 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 152 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 153 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 154 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 155 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 156 | CLANG_WARN_STRICT_PROTOTYPES = YES; 157 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 158 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 159 | CLANG_WARN_UNREACHABLE_CODE = YES; 160 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 161 | COPY_PHASE_STRIP = NO; 162 | DEBUG_INFORMATION_FORMAT = dwarf; 163 | ENABLE_STRICT_OBJC_MSGSEND = YES; 164 | ENABLE_TESTABILITY = YES; 165 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 166 | GCC_C_LANGUAGE_STANDARD = gnu17; 167 | GCC_DYNAMIC_NO_PIC = NO; 168 | GCC_NO_COMMON_BLOCKS = YES; 169 | GCC_OPTIMIZATION_LEVEL = 0; 170 | GCC_PREPROCESSOR_DEFINITIONS = ( 171 | "DEBUG=1", 172 | "$(inherited)", 173 | ); 174 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 175 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 176 | GCC_WARN_UNDECLARED_SELECTOR = YES; 177 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 178 | GCC_WARN_UNUSED_FUNCTION = YES; 179 | GCC_WARN_UNUSED_VARIABLE = YES; 180 | IPHONEOS_DEPLOYMENT_TARGET = 18.0; 181 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 182 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 183 | MTL_FAST_MATH = YES; 184 | ONLY_ACTIVE_ARCH = YES; 185 | SDKROOT = iphoneos; 186 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; 187 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 188 | }; 189 | name = Debug; 190 | }; 191 | ECD8CAB82E716C1D00926D13 /* Release */ = { 192 | isa = XCBuildConfiguration; 193 | buildSettings = { 194 | ALWAYS_SEARCH_USER_PATHS = NO; 195 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 196 | CLANG_ANALYZER_NONNULL = YES; 197 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 198 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 199 | CLANG_ENABLE_MODULES = YES; 200 | CLANG_ENABLE_OBJC_ARC = YES; 201 | CLANG_ENABLE_OBJC_WEAK = YES; 202 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 203 | CLANG_WARN_BOOL_CONVERSION = YES; 204 | CLANG_WARN_COMMA = YES; 205 | CLANG_WARN_CONSTANT_CONVERSION = YES; 206 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 207 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 208 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 209 | CLANG_WARN_EMPTY_BODY = YES; 210 | CLANG_WARN_ENUM_CONVERSION = YES; 211 | CLANG_WARN_INFINITE_RECURSION = YES; 212 | CLANG_WARN_INT_CONVERSION = YES; 213 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 214 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 215 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 216 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 217 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 218 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 219 | CLANG_WARN_STRICT_PROTOTYPES = YES; 220 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 221 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 222 | CLANG_WARN_UNREACHABLE_CODE = YES; 223 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 224 | COPY_PHASE_STRIP = NO; 225 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 226 | ENABLE_NS_ASSERTIONS = NO; 227 | ENABLE_STRICT_OBJC_MSGSEND = YES; 228 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 229 | GCC_C_LANGUAGE_STANDARD = gnu17; 230 | GCC_NO_COMMON_BLOCKS = YES; 231 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 232 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 233 | GCC_WARN_UNDECLARED_SELECTOR = YES; 234 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 235 | GCC_WARN_UNUSED_FUNCTION = YES; 236 | GCC_WARN_UNUSED_VARIABLE = YES; 237 | IPHONEOS_DEPLOYMENT_TARGET = 18.0; 238 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 239 | MTL_ENABLE_DEBUG_INFO = NO; 240 | MTL_FAST_MATH = YES; 241 | SDKROOT = iphoneos; 242 | SWIFT_COMPILATION_MODE = wholemodule; 243 | VALIDATE_PRODUCT = YES; 244 | }; 245 | name = Release; 246 | }; 247 | ECD8CABA2E716C1D00926D13 /* Debug */ = { 248 | isa = XCBuildConfiguration; 249 | buildSettings = { 250 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 251 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 252 | CODE_SIGN_STYLE = Automatic; 253 | CURRENT_PROJECT_VERSION = 1; 254 | DEVELOPMENT_ASSET_PATHS = "\"Lecture5-Forms/Preview Content\""; 255 | ENABLE_PREVIEWS = YES; 256 | GENERATE_INFOPLIST_FILE = YES; 257 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 258 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 259 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 260 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 261 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 262 | LD_RUNPATH_SEARCH_PATHS = ( 263 | "$(inherited)", 264 | "@executable_path/Frameworks", 265 | ); 266 | MARKETING_VERSION = 1.0; 267 | PRODUCT_BUNDLE_IDENTIFIER = "no.hakonbogen.Lecture5-Forms"; 268 | PRODUCT_NAME = "$(TARGET_NAME)"; 269 | SWIFT_EMIT_LOC_STRINGS = YES; 270 | SWIFT_VERSION = 5.0; 271 | TARGETED_DEVICE_FAMILY = "1,2"; 272 | }; 273 | name = Debug; 274 | }; 275 | ECD8CABB2E716C1D00926D13 /* Release */ = { 276 | isa = XCBuildConfiguration; 277 | buildSettings = { 278 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 279 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 280 | CODE_SIGN_STYLE = Automatic; 281 | CURRENT_PROJECT_VERSION = 1; 282 | DEVELOPMENT_ASSET_PATHS = "\"Lecture5-Forms/Preview Content\""; 283 | ENABLE_PREVIEWS = YES; 284 | GENERATE_INFOPLIST_FILE = YES; 285 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 286 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 287 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 288 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 289 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 290 | LD_RUNPATH_SEARCH_PATHS = ( 291 | "$(inherited)", 292 | "@executable_path/Frameworks", 293 | ); 294 | MARKETING_VERSION = 1.0; 295 | PRODUCT_BUNDLE_IDENTIFIER = "no.hakonbogen.Lecture5-Forms"; 296 | PRODUCT_NAME = "$(TARGET_NAME)"; 297 | SWIFT_EMIT_LOC_STRINGS = YES; 298 | SWIFT_VERSION = 5.0; 299 | TARGETED_DEVICE_FAMILY = "1,2"; 300 | }; 301 | name = Release; 302 | }; 303 | /* End XCBuildConfiguration section */ 304 | 305 | /* Begin XCConfigurationList section */ 306 | ECD8CAA62E716C1B00926D13 /* Build configuration list for PBXProject "Lecture5-Forms" */ = { 307 | isa = XCConfigurationList; 308 | buildConfigurations = ( 309 | ECD8CAB72E716C1D00926D13 /* Debug */, 310 | ECD8CAB82E716C1D00926D13 /* Release */, 311 | ); 312 | defaultConfigurationIsVisible = 0; 313 | defaultConfigurationName = Release; 314 | }; 315 | ECD8CAB92E716C1D00926D13 /* Build configuration list for PBXNativeTarget "Lecture5-Forms" */ = { 316 | isa = XCConfigurationList; 317 | buildConfigurations = ( 318 | ECD8CABA2E716C1D00926D13 /* Debug */, 319 | ECD8CABB2E716C1D00926D13 /* Release */, 320 | ); 321 | defaultConfigurationIsVisible = 0; 322 | defaultConfigurationName = Release; 323 | }; 324 | /* End XCConfigurationList section */ 325 | }; 326 | rootObject = ECD8CAA32E716C1B00926D13 /* Project object */; 327 | } 328 | -------------------------------------------------------------------------------- /Forelesning7/Forelesning7.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 77; 7 | objects = { 8 | 9 | /* Begin PBXFileReference section */ 10 | ECF86BB72E795506003947A9 /* Forelesning7.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Forelesning7.app; sourceTree = BUILT_PRODUCTS_DIR; }; 11 | /* End PBXFileReference section */ 12 | 13 | /* Begin PBXFileSystemSynchronizedRootGroup section */ 14 | ECF86BB92E795506003947A9 /* Forelesning7 */ = { 15 | isa = PBXFileSystemSynchronizedRootGroup; 16 | path = Forelesning7; 17 | sourceTree = ""; 18 | }; 19 | /* End PBXFileSystemSynchronizedRootGroup section */ 20 | 21 | /* Begin PBXFrameworksBuildPhase section */ 22 | ECF86BB42E795506003947A9 /* Frameworks */ = { 23 | isa = PBXFrameworksBuildPhase; 24 | buildActionMask = 2147483647; 25 | files = ( 26 | ); 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXFrameworksBuildPhase section */ 30 | 31 | /* Begin PBXGroup section */ 32 | ECF86BAE2E795506003947A9 = { 33 | isa = PBXGroup; 34 | children = ( 35 | ECF86BB92E795506003947A9 /* Forelesning7 */, 36 | ECF86BB82E795506003947A9 /* Products */, 37 | ); 38 | sourceTree = ""; 39 | }; 40 | ECF86BB82E795506003947A9 /* Products */ = { 41 | isa = PBXGroup; 42 | children = ( 43 | ECF86BB72E795506003947A9 /* Forelesning7.app */, 44 | ); 45 | name = Products; 46 | sourceTree = ""; 47 | }; 48 | /* End PBXGroup section */ 49 | 50 | /* Begin PBXNativeTarget section */ 51 | ECF86BB62E795506003947A9 /* Forelesning7 */ = { 52 | isa = PBXNativeTarget; 53 | buildConfigurationList = ECF86BC22E795513003947A9 /* Build configuration list for PBXNativeTarget "Forelesning7" */; 54 | buildPhases = ( 55 | ECF86BB32E795506003947A9 /* Sources */, 56 | ECF86BB42E795506003947A9 /* Frameworks */, 57 | ECF86BB52E795506003947A9 /* Resources */, 58 | ); 59 | buildRules = ( 60 | ); 61 | dependencies = ( 62 | ); 63 | fileSystemSynchronizedGroups = ( 64 | ECF86BB92E795506003947A9 /* Forelesning7 */, 65 | ); 66 | name = Forelesning7; 67 | packageProductDependencies = ( 68 | ); 69 | productName = Forelesning7; 70 | productReference = ECF86BB72E795506003947A9 /* Forelesning7.app */; 71 | productType = "com.apple.product-type.application"; 72 | }; 73 | /* End PBXNativeTarget section */ 74 | 75 | /* Begin PBXProject section */ 76 | ECF86BAF2E795506003947A9 /* Project object */ = { 77 | isa = PBXProject; 78 | attributes = { 79 | BuildIndependentTargetsInParallel = 1; 80 | LastSwiftUpdateCheck = 2600; 81 | LastUpgradeCheck = 2600; 82 | TargetAttributes = { 83 | ECF86BB62E795506003947A9 = { 84 | CreatedOnToolsVersion = 26.0; 85 | }; 86 | }; 87 | }; 88 | buildConfigurationList = ECF86BB22E795506003947A9 /* Build configuration list for PBXProject "Forelesning7" */; 89 | developmentRegion = en; 90 | hasScannedForEncodings = 0; 91 | knownRegions = ( 92 | en, 93 | Base, 94 | ); 95 | mainGroup = ECF86BAE2E795506003947A9; 96 | minimizedProjectReferenceProxies = 1; 97 | preferredProjectObjectVersion = 77; 98 | productRefGroup = ECF86BB82E795506003947A9 /* Products */; 99 | projectDirPath = ""; 100 | projectRoot = ""; 101 | targets = ( 102 | ECF86BB62E795506003947A9 /* Forelesning7 */, 103 | ); 104 | }; 105 | /* End PBXProject section */ 106 | 107 | /* Begin PBXResourcesBuildPhase section */ 108 | ECF86BB52E795506003947A9 /* Resources */ = { 109 | isa = PBXResourcesBuildPhase; 110 | buildActionMask = 2147483647; 111 | files = ( 112 | ); 113 | runOnlyForDeploymentPostprocessing = 0; 114 | }; 115 | /* End PBXResourcesBuildPhase section */ 116 | 117 | /* Begin PBXSourcesBuildPhase section */ 118 | ECF86BB32E795506003947A9 /* Sources */ = { 119 | isa = PBXSourcesBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXSourcesBuildPhase section */ 126 | 127 | /* Begin XCBuildConfiguration section */ 128 | ECF86BC02E795513003947A9 /* Debug */ = { 129 | isa = XCBuildConfiguration; 130 | buildSettings = { 131 | ALWAYS_SEARCH_USER_PATHS = NO; 132 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 133 | CLANG_ANALYZER_NONNULL = YES; 134 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 135 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 136 | CLANG_ENABLE_MODULES = YES; 137 | CLANG_ENABLE_OBJC_ARC = YES; 138 | CLANG_ENABLE_OBJC_WEAK = YES; 139 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 140 | CLANG_WARN_BOOL_CONVERSION = YES; 141 | CLANG_WARN_COMMA = YES; 142 | CLANG_WARN_CONSTANT_CONVERSION = YES; 143 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 144 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 145 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 146 | CLANG_WARN_EMPTY_BODY = YES; 147 | CLANG_WARN_ENUM_CONVERSION = YES; 148 | CLANG_WARN_INFINITE_RECURSION = YES; 149 | CLANG_WARN_INT_CONVERSION = YES; 150 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 151 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 152 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 153 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 154 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 155 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 156 | CLANG_WARN_STRICT_PROTOTYPES = YES; 157 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 158 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 159 | CLANG_WARN_UNREACHABLE_CODE = YES; 160 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 161 | COPY_PHASE_STRIP = NO; 162 | DEBUG_INFORMATION_FORMAT = dwarf; 163 | DEVELOPMENT_TEAM = 5PKTA338CL; 164 | ENABLE_STRICT_OBJC_MSGSEND = YES; 165 | ENABLE_TESTABILITY = YES; 166 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 167 | GCC_C_LANGUAGE_STANDARD = gnu17; 168 | GCC_DYNAMIC_NO_PIC = NO; 169 | GCC_NO_COMMON_BLOCKS = YES; 170 | GCC_OPTIMIZATION_LEVEL = 0; 171 | GCC_PREPROCESSOR_DEFINITIONS = ( 172 | "DEBUG=1", 173 | "$(inherited)", 174 | ); 175 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 176 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 177 | GCC_WARN_UNDECLARED_SELECTOR = YES; 178 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 179 | GCC_WARN_UNUSED_FUNCTION = YES; 180 | GCC_WARN_UNUSED_VARIABLE = YES; 181 | IPHONEOS_DEPLOYMENT_TARGET = 26.0; 182 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 183 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 184 | MTL_FAST_MATH = YES; 185 | ONLY_ACTIVE_ARCH = YES; 186 | SDKROOT = iphoneos; 187 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; 188 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 189 | }; 190 | name = Debug; 191 | }; 192 | ECF86BC12E795513003947A9 /* Release */ = { 193 | isa = XCBuildConfiguration; 194 | buildSettings = { 195 | ALWAYS_SEARCH_USER_PATHS = NO; 196 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; 197 | CLANG_ANALYZER_NONNULL = YES; 198 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 199 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 200 | CLANG_ENABLE_MODULES = YES; 201 | CLANG_ENABLE_OBJC_ARC = YES; 202 | CLANG_ENABLE_OBJC_WEAK = YES; 203 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 204 | CLANG_WARN_BOOL_CONVERSION = YES; 205 | CLANG_WARN_COMMA = YES; 206 | CLANG_WARN_CONSTANT_CONVERSION = YES; 207 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 208 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 209 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 210 | CLANG_WARN_EMPTY_BODY = YES; 211 | CLANG_WARN_ENUM_CONVERSION = YES; 212 | CLANG_WARN_INFINITE_RECURSION = YES; 213 | CLANG_WARN_INT_CONVERSION = YES; 214 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 215 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 216 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 217 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 218 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 219 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 220 | CLANG_WARN_STRICT_PROTOTYPES = YES; 221 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 222 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 223 | CLANG_WARN_UNREACHABLE_CODE = YES; 224 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 225 | COPY_PHASE_STRIP = NO; 226 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 227 | DEVELOPMENT_TEAM = 5PKTA338CL; 228 | ENABLE_NS_ASSERTIONS = NO; 229 | ENABLE_STRICT_OBJC_MSGSEND = YES; 230 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 231 | GCC_C_LANGUAGE_STANDARD = gnu17; 232 | GCC_NO_COMMON_BLOCKS = YES; 233 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 234 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 235 | GCC_WARN_UNDECLARED_SELECTOR = YES; 236 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 237 | GCC_WARN_UNUSED_FUNCTION = YES; 238 | GCC_WARN_UNUSED_VARIABLE = YES; 239 | IPHONEOS_DEPLOYMENT_TARGET = 26.0; 240 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES; 241 | MTL_ENABLE_DEBUG_INFO = NO; 242 | MTL_FAST_MATH = YES; 243 | SDKROOT = iphoneos; 244 | SWIFT_COMPILATION_MODE = wholemodule; 245 | VALIDATE_PRODUCT = YES; 246 | }; 247 | name = Release; 248 | }; 249 | ECF86BC32E795513003947A9 /* Debug */ = { 250 | isa = XCBuildConfiguration; 251 | buildSettings = { 252 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 253 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 254 | CODE_SIGN_STYLE = Automatic; 255 | CURRENT_PROJECT_VERSION = 1; 256 | DEVELOPMENT_TEAM = 5PKTA338CL; 257 | ENABLE_PREVIEWS = YES; 258 | GENERATE_INFOPLIST_FILE = YES; 259 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 260 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 261 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 262 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 263 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 264 | LD_RUNPATH_SEARCH_PATHS = ( 265 | "$(inherited)", 266 | "@executable_path/Frameworks", 267 | ); 268 | MARKETING_VERSION = 1.0; 269 | PRODUCT_BUNDLE_IDENTIFIER = no.hakonbogen.test.Forelesning7; 270 | PRODUCT_NAME = "$(TARGET_NAME)"; 271 | STRING_CATALOG_GENERATE_SYMBOLS = YES; 272 | SWIFT_APPROACHABLE_CONCURRENCY = YES; 273 | SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; 274 | SWIFT_EMIT_LOC_STRINGS = YES; 275 | SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; 276 | SWIFT_VERSION = 5.0; 277 | TARGETED_DEVICE_FAMILY = "1,2"; 278 | }; 279 | name = Debug; 280 | }; 281 | ECF86BC42E795513003947A9 /* Release */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 285 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 286 | CODE_SIGN_STYLE = Automatic; 287 | CURRENT_PROJECT_VERSION = 1; 288 | DEVELOPMENT_TEAM = 5PKTA338CL; 289 | ENABLE_PREVIEWS = YES; 290 | GENERATE_INFOPLIST_FILE = YES; 291 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 292 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 293 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 294 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 295 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 296 | LD_RUNPATH_SEARCH_PATHS = ( 297 | "$(inherited)", 298 | "@executable_path/Frameworks", 299 | ); 300 | MARKETING_VERSION = 1.0; 301 | PRODUCT_BUNDLE_IDENTIFIER = no.hakonbogen.test.Forelesning7; 302 | PRODUCT_NAME = "$(TARGET_NAME)"; 303 | STRING_CATALOG_GENERATE_SYMBOLS = YES; 304 | SWIFT_APPROACHABLE_CONCURRENCY = YES; 305 | SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; 306 | SWIFT_EMIT_LOC_STRINGS = YES; 307 | SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; 308 | SWIFT_VERSION = 5.0; 309 | TARGETED_DEVICE_FAMILY = "1,2"; 310 | }; 311 | name = Release; 312 | }; 313 | /* End XCBuildConfiguration section */ 314 | 315 | /* Begin XCConfigurationList section */ 316 | ECF86BB22E795506003947A9 /* Build configuration list for PBXProject "Forelesning7" */ = { 317 | isa = XCConfigurationList; 318 | buildConfigurations = ( 319 | ECF86BC02E795513003947A9 /* Debug */, 320 | ECF86BC12E795513003947A9 /* Release */, 321 | ); 322 | defaultConfigurationIsVisible = 0; 323 | defaultConfigurationName = Release; 324 | }; 325 | ECF86BC22E795513003947A9 /* Build configuration list for PBXNativeTarget "Forelesning7" */ = { 326 | isa = XCConfigurationList; 327 | buildConfigurations = ( 328 | ECF86BC32E795513003947A9 /* Debug */, 329 | ECF86BC42E795513003947A9 /* Release */, 330 | ); 331 | defaultConfigurationIsVisible = 0; 332 | defaultConfigurationName = Release; 333 | }; 334 | /* End XCConfigurationList section */ 335 | }; 336 | rootObject = ECF86BAF2E795506003947A9 /* Project object */; 337 | } 338 | --------------------------------------------------------------------------------