Skip to content

Commit ec9be7a

Browse files
Migrated to swift 6
1 parent 78366c9 commit ec9be7a

11 files changed

Lines changed: 320 additions & 129 deletions

File tree

.DS_Store

6 KB
Binary file not shown.

SwiftUIExamples/.DS_Store

6 KB
Binary file not shown.

SwiftUIExamples/SwiftUIExamples.xcodeproj/project.pbxproj

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@
261261
attributes = {
262262
BuildIndependentTargetsInParallel = 1;
263263
LastSwiftUpdateCheck = 1520;
264-
LastUpgradeCheck = 1520;
264+
LastUpgradeCheck = 1640;
265265
TargetAttributes = {
266266
10525C7B2E2D2D9800D7C510 = {
267267
CreatedOnToolsVersion = 15.2;
@@ -377,7 +377,7 @@
377377
PRODUCT_BUNDLE_IDENTIFIER = com.swiftuiapp.sample.SwiftUIExamplesTests;
378378
PRODUCT_NAME = "$(TARGET_NAME)";
379379
SWIFT_EMIT_LOC_STRINGS = NO;
380-
SWIFT_VERSION = 5.0;
380+
SWIFT_VERSION = 6.0;
381381
TARGETED_DEVICE_FAMILY = "1,2";
382382
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SwiftUIExamples.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/SwiftUIExamples";
383383
};
@@ -394,7 +394,7 @@
394394
PRODUCT_BUNDLE_IDENTIFIER = com.swiftuiapp.sample.SwiftUIExamplesTests;
395395
PRODUCT_NAME = "$(TARGET_NAME)";
396396
SWIFT_EMIT_LOC_STRINGS = NO;
397-
SWIFT_VERSION = 5.0;
397+
SWIFT_VERSION = 6.0;
398398
TARGETED_DEVICE_FAMILY = "1,2";
399399
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SwiftUIExamples.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/SwiftUIExamples";
400400
};
@@ -404,21 +404,23 @@
404404
isa = XCBuildConfiguration;
405405
buildSettings = {
406406
CODE_SIGN_STYLE = Automatic;
407+
DEAD_CODE_STRIPPING = YES;
407408
MACOSX_DEPLOYMENT_TARGET = 13.7;
408409
PRODUCT_NAME = "$(TARGET_NAME)";
409410
SDKROOT = macosx;
410-
SWIFT_VERSION = 5.0;
411+
SWIFT_VERSION = 6.0;
411412
};
412413
name = Debug;
413414
};
414415
109998102E24DAA600A8A3C9 /* Release */ = {
415416
isa = XCBuildConfiguration;
416417
buildSettings = {
417418
CODE_SIGN_STYLE = Automatic;
419+
DEAD_CODE_STRIPPING = YES;
418420
MACOSX_DEPLOYMENT_TARGET = 13.7;
419421
PRODUCT_NAME = "$(TARGET_NAME)";
420422
SDKROOT = macosx;
421-
SWIFT_VERSION = 5.0;
423+
SWIFT_VERSION = 6.0;
422424
};
423425
name = Release;
424426
};
@@ -482,6 +484,7 @@
482484
SDKROOT = iphoneos;
483485
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
484486
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
487+
SWIFT_VERSION = 6.0;
485488
};
486489
name = Debug;
487490
};
@@ -537,6 +540,7 @@
537540
MTL_FAST_MATH = YES;
538541
SDKROOT = iphoneos;
539542
SWIFT_COMPILATION_MODE = wholemodule;
543+
SWIFT_VERSION = 6.0;
540544
VALIDATE_PRODUCT = YES;
541545
};
542546
name = Release;
@@ -564,7 +568,8 @@
564568
PRODUCT_BUNDLE_IDENTIFIER = com.swiftuiapp.sample.SwiftUIExamples;
565569
PRODUCT_NAME = "$(TARGET_NAME)";
566570
SWIFT_EMIT_LOC_STRINGS = YES;
567-
SWIFT_VERSION = 5.0;
571+
SWIFT_STRICT_CONCURRENCY = complete;
572+
SWIFT_VERSION = 6.0;
568573
TARGETED_DEVICE_FAMILY = "1,2";
569574
};
570575
name = Debug;
@@ -592,7 +597,8 @@
592597
PRODUCT_BUNDLE_IDENTIFIER = com.swiftuiapp.sample.SwiftUIExamples;
593598
PRODUCT_NAME = "$(TARGET_NAME)";
594599
SWIFT_EMIT_LOC_STRINGS = YES;
595-
SWIFT_VERSION = 5.0;
600+
SWIFT_STRICT_CONCURRENCY = complete;
601+
SWIFT_VERSION = 6.0;
596602
TARGETED_DEVICE_FAMILY = "1,2";
597603
};
598604
name = Release;
6 KB
Binary file not shown.
Lines changed: 52 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,75 @@
1-
//
2-
// RepoListDIApp.swift
3-
// Complete iOS App using MVVM with Dependency Injection
4-
//
5-
61
import SwiftUI
72

8-
// MARK: - View
3+
// MARK: - Protocol
94

10-
struct ProjectsListView: View {
11-
@StateObject var viewModel: RepoViewModel
5+
protocol RepoServiceProtocol: Sendable {
6+
// func fetchRepos(completion: @escaping ([String]) -> Void)
7+
// clouser replaced with async
8+
func fetchRepos() async -> [String]
9+
}
1210

13-
var body: some View {
14-
NavigationView {
15-
List(viewModel.repos, id: \.self) { repo in
16-
Text(repo)
17-
}
18-
.navigationTitle("Projects")
19-
.onAppear {
20-
viewModel.loadRepos()
21-
}
22-
}
11+
// MARK: - Real Service
12+
13+
final class RepoService: RepoServiceProtocol {
14+
func fetchRepos() async -> [String] {
15+
try? await Task.sleep(nanoseconds: 1_000_000_000) // Simulate 1 second delay
16+
return ["Swift", "Combine", "UIKit", "CoreData"]
2317
}
2418
}
2519

20+
// MARK: - Mock Service (for previews or unit tests)
21+
22+
final class MockRepoService: RepoServiceProtocol {
23+
func fetchRepos() async -> [String] {
24+
return ["MockRepo1", "MockRepo2"]
25+
}
26+
}
2627

2728
// MARK: - ViewModel
2829

29-
class RepoViewModel: ObservableObject {
30+
@MainActor
31+
final class RepoViewModel: ObservableObject {
3032
@Published var repos: [String] = []
31-
private let service: RepoServiceProtocol
32-
33-
init(service: RepoServiceProtocol) {
33+
private let service: any RepoServiceProtocol
34+
35+
init(service: any RepoServiceProtocol) {
3436
self.service = service
3537
}
36-
37-
func loadRepos() {
38-
service.fetchRepos { [weak self] result in
39-
DispatchQueue.main.async {
40-
self?.repos = result
41-
}
42-
}
38+
39+
// fetchRepos() is nonisolated — it won’t run on MainActor.
40+
nonisolated func loadRepos() async {
41+
// This runs on background thread
42+
let repos = await service.fetchRepos()
43+
44+
// Switch to main actor for UI update
45+
await setRepos(repos)
46+
}
47+
48+
private func setRepos(_ repos: [String]) {
49+
self.repos = repos
4350
}
4451
}
4552

53+
// MARK: - View
4654

47-
// MARK: - Protocol
48-
49-
protocol RepoServiceProtocol {
50-
func fetchRepos(completion: @escaping ([String]) -> Void)
51-
}
52-
53-
54-
// MARK: - Real Service
55-
56-
class RepoService: RepoServiceProtocol {
57-
func fetchRepos(completion: @escaping ([String]) -> Void) {
58-
// Simulate API delay
59-
DispatchQueue.global().asyncAfter(deadline: .now() + 1.0) {
60-
completion(["Swift", "Combine", "UIKit", "CoreData"])
55+
struct ProjectsListView: View {
56+
@StateObject var viewModel: RepoViewModel
57+
58+
var body: some View {
59+
NavigationView {
60+
List(viewModel.repos, id: \.self) { repo in
61+
Text(repo)
62+
}
63+
.navigationTitle("Projects")
64+
.task {
65+
await viewModel.loadRepos()
66+
}
6167
}
6268
}
6369
}
6470

65-
66-
// MARK: - Mock Service (for unit tests or previews)
67-
68-
class MockRepoService: RepoServiceProtocol {
69-
func fetchRepos(completion: @escaping ([String]) -> Void) {
70-
completion(["MockRepo1", "MockRepo2"])
71+
struct ProjectsListView_Previews: PreviewProvider {
72+
static var previews: some View {
73+
ProjectsListView(viewModel: .init(service: MockRepoService()))
7174
}
7275
}

SwiftUIExamples/SwiftUIExamples/AsyncAwait/UserListAsyncStaticData.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ struct UserModel: Identifiable, Decodable {
1616

1717
// MARK: - Protocol for User Service
1818

19+
@MainActor
1920
protocol UserServiceProtocol {
2021
func fetchUsers() async throws -> [UserModel]
2122
}
@@ -31,7 +32,7 @@ class UserService: UserServiceProtocol {
3132
}
3233

3334
// MARK: - ViewModel Protocol
34-
35+
@MainActor
3536
protocol UserListViewModelProtocol: ObservableObject {
3637
var users: [UserModel] { get }
3738
var isLoading: Bool { get }
@@ -65,7 +66,7 @@ class UserListViewModel: UserListViewModelProtocol {
6566
}
6667

6768
// MARK: - SwiftUI View
68-
69+
@MainActor
6970
struct UserListView<VM: UserListViewModelProtocol>: View {
7071
@StateObject private var viewModel: VM
7172

0 commit comments

Comments
 (0)