Skip to content

Commit 54858e1

Browse files
authored
Xcode26 / Swift 6 - Minimal changes for successful builds (#1222)
* Minimal changes to get builds running in XCode26 with Swift 6. * Removing unnecessary comment * - SmilieSearchViewModel: Use NSManagedObjectID to safely pass Smilie objects across concurrency boundaries in updateLastUsedDate(). Access managed object properties only within context.perform block. - PostsPageViewController: Add comment explaining why networkOperation uses Any? type (Task returns non-Sendable Core Data objects; Swift 6 requires Sendable Success types).
1 parent a624e3e commit 54858e1

File tree

6 files changed

+29
-14
lines changed

6 files changed

+29
-14
lines changed

App/Composition/SmiliePicker/SmilieSearchViewModel.swift

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -197,12 +197,24 @@ final class SmilieSearchViewModel: ObservableObject {
197197

198198
func updateLastUsedDate(for smilie: Smilie) {
199199
guard let context = dataStore.managedObjectContext else { return }
200-
context.perform {
201-
smilie.metadata.lastUsedDate = Date()
202-
do {
203-
try context.save()
204-
} catch {
205-
print("Error saving last used date: \(error)")
200+
let smilieID = smilie.objectID
201+
Task {
202+
await context.perform {
203+
guard let smilie = context.object(with: smilieID) as? Smilie,
204+
let smilieText = smilie.text else { return }
205+
206+
let fetchRequest = NSFetchRequest<Smilie>(entityName: "Smilie")
207+
fetchRequest.predicate = NSPredicate(format: "text == %@", smilieText)
208+
fetchRequest.fetchLimit = 1
209+
210+
do {
211+
if let smilie = try context.fetch(fetchRequest).first {
212+
smilie.metadata.lastUsedDate = Date()
213+
try context.save()
214+
}
215+
} catch {
216+
print("Error saving last used date: \(error)")
217+
}
206218
}
207219
}
208220
}

App/Refreshers/AnnouncementListRefresher.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// Copyright 2017 Awful Contributors. CC BY-NC-SA 3.0 US https://github.com/Awful/Awful.app
44

55
import AwfulCore
6-
import CoreData
6+
@preconcurrency import CoreData
77
import os
88
import UIKit
99

App/View Controllers/Posts/PostsPageViewController.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
//
33
// Copyright 2016 Awful Contributors. CC BY-NC-SA 3.0 US https://github.com/Awful/Awful.app
44

5-
import AwfulCore
5+
@preconcurrency import AwfulCore
66
import AwfulModelTypes
77
import AwfulSettings
88
import AwfulTheming
99
import Combine
10-
import CoreData
10+
@preconcurrency import CoreData
1111
import MobileCoreServices
1212
import MRProgress
1313
import os
@@ -41,7 +41,9 @@ final class PostsPageViewController: ViewController {
4141
@FoilDefaultStorage(Settings.jumpToPostEndOnDoubleTap) private var jumpToPostEndOnDoubleTap
4242
private var jumpToPostIDAfterLoading: String?
4343
private var messageViewController: MessageComposeViewController?
44-
private var networkOperation: Task<(posts: [Post], firstUnreadPost: Int?, advertisementHTML: String), Error>?
44+
// Stored as Any because Task returns non-Sendable Core Data objects (Post: NSManagedObject).
45+
// Swift 6 requires Task<Success, Failure> Success types to be Sendable.
46+
private var networkOperation: Any?
4547
private var observers: [NSKeyValueObservation] = []
4648
private lazy var oEmbedFetcher: OEmbedFetcher = .init()
4749
private(set) var page: ThreadPage?
@@ -160,7 +162,7 @@ final class PostsPageViewController: ViewController {
160162
}
161163

162164
deinit {
163-
networkOperation?.cancel()
165+
(networkOperation as? Task<(posts: [Post], firstUnreadPost: Int?, advertisementHTML: String), Error>)?.cancel()
164166
}
165167

166168
var posts: [Post] = []
@@ -198,7 +200,7 @@ final class PostsPageViewController: ViewController {
198200
) {
199201
flagRequest?.cancel()
200202
flagRequest = nil
201-
networkOperation?.cancel()
203+
(networkOperation as? Task<(posts: [Post], firstUnreadPost: Int?, advertisementHTML: String), Error>)?.cancel()
202204
networkOperation = nil
203205

204206
// prevent white flash caused by webview being opaque during refreshes

AwfulCore/Sources/AwfulCore/Model/AwfulManagedObject.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import CoreData
66

77
/// A slightly more convenient NSManagedObject for entities with a custom class.
8-
public class AwfulManagedObject: NSManagedObject {
8+
public class AwfulManagedObject: NSManagedObject, @unchecked Sendable {
99
public var objectKey: AwfulObjectKey {
1010
fatalError("subclass implementation please")
1111
}

AwfulCore/Sources/AwfulCore/Model/Post.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import CoreData
66

77
/// A single reply to a thread.
88
@objc(Post)
9-
public class Post: AwfulManagedObject, Managed {
9+
public class Post: AwfulManagedObject, Managed, @unchecked Sendable {
1010
public static var entityName: String { "Post" }
1111

1212
/// Whether the logged-in user can edit the post.

Config/Common.xcconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ RUN_CLANG_STATIC_ANALYZER = YES
7575
SDKROOT = iphoneos
7676

7777
SWIFT_EMIT_LOC_STRINGS = YES
78+
SWIFT_STRICT_CONCURRENCY = minimal
7879
SWIFT_TREAT_WARNINGS_AS_ERRORS = YES
7980
SWIFT_VERSION = 5.0
8081

0 commit comments

Comments
 (0)