├── 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 |
--------------------------------------------------------------------------------