diff --git a/FetchRequests.xcodeproj/project.pbxproj b/FetchRequests.xcodeproj/project.pbxproj index 6459fbc..931f23a 100644 --- a/FetchRequests.xcodeproj/project.pbxproj +++ b/FetchRequests.xcodeproj/project.pbxproj @@ -768,7 +768,7 @@ BuildIndependentTargetsInParallel = YES; CLASSPREFIX = ""; LastSwiftUpdateCheck = 1100; - LastUpgradeCheck = 1530; + LastUpgradeCheck = 1540; ORGANIZATIONNAME = "Speramus Inc."; TargetAttributes = { 471C506B22C6D0DB007F73E9 = { @@ -1215,6 +1215,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; APPLICATION_EXTENSION_API_ONLY = YES; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -1283,7 +1284,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_STRICT_CONCURRENCY = targeted; + SWIFT_STRICT_CONCURRENCY = complete; SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = ""; @@ -1300,6 +1301,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; APPLICATION_EXTENSION_API_ONLY = YES; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -1361,7 +1363,7 @@ SKIP_INSTALL = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_STRICT_CONCURRENCY = targeted; + SWIFT_STRICT_CONCURRENCY = complete; SWIFT_SWIFT3_OBJC_INFERENCE = Off; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = ""; diff --git a/FetchRequests.xcodeproj/xcshareddata/xcschemes/FetchRequests-iOS.xcscheme b/FetchRequests.xcodeproj/xcshareddata/xcschemes/FetchRequests-iOS.xcscheme index d7f5883..fb9c252 100644 --- a/FetchRequests.xcodeproj/xcshareddata/xcschemes/FetchRequests-iOS.xcscheme +++ b/FetchRequests.xcodeproj/xcshareddata/xcschemes/FetchRequests-iOS.xcscheme @@ -1,6 +1,6 @@ : Hashable { var keyPath: PartialKeyPath } -class FetchableAssociatedValueReference: AssociatedValueReference { +class FetchableAssociatedValueReference: AssociatedValueReference, @unchecked Sendable { private var observations: [Entity: [InvalidatableToken]] = [:] fileprivate override func stopObservingValue() { diff --git a/FetchRequests/Sources/Controller/CollapsibleSectionsFetchedResultsController.swift b/FetchRequests/Sources/Controller/CollapsibleSectionsFetchedResultsController.swift index 55d3dca..4955be6 100644 --- a/FetchRequests/Sources/Controller/CollapsibleSectionsFetchedResultsController.swift +++ b/FetchRequests/Sources/Controller/CollapsibleSectionsFetchedResultsController.swift @@ -266,14 +266,16 @@ public extension CollapsibleSectionsFetchedResultsController { // MARK: - Fetch Methods public extension CollapsibleSectionsFetchedResultsController { @MainActor - func performFetch(completion: @escaping @MainActor () -> Void = {}) { + func performFetch( + completion: @escaping @MainActor @Sendable () -> Void = {} + ) { fetchController.performFetch(completion: completion) } @MainActor func resort( using newSortDescriptors: [NSSortDescriptor], - completion: @escaping @MainActor () -> Void = {} + completion: @escaping @MainActor @Sendable () -> Void = {} ) { fetchController.resort(using: newSortDescriptors, completion: completion) } diff --git a/FetchRequests/Sources/Controller/FetchedResultsController.swift b/FetchRequests/Sources/Controller/FetchedResultsController.swift index 265dc66..0ae22ed 100644 --- a/FetchRequests/Sources/Controller/FetchedResultsController.swift +++ b/FetchRequests/Sources/Controller/FetchedResultsController.swift @@ -18,7 +18,7 @@ import WatchKit // MARK: - Delegate -public enum FetchedResultsChange: Equatable { +public enum FetchedResultsChange: Equatable, Sendable { case insert(location: Location) case delete(location: Location) case update(location: Location) @@ -151,7 +151,7 @@ public enum FetchedResultsError: Error { // MARK: - Sections -public struct FetchedResultsSection: Equatable, Identifiable { +public struct FetchedResultsSection: Equatable, Identifiable, Sendable { public let name: String public fileprivate(set) var objects: [FetchedObject] @@ -171,7 +171,10 @@ public struct FetchedResultsSection: Equatable, // MARK: - FetchedResultsController -func performOnMainThread(async: Bool = true, handler: @escaping @MainActor () -> Void) { +func performOnMainThread( + async: Bool = true, + handler: @escaping @MainActor @Sendable () -> Void +) { @MainActor(unsafe) func unsafeHandler() { handler() @@ -188,7 +191,7 @@ func performOnMainThread(async: Bool = true, handler: @escaping @MainActor () -> } } -public class FetchedResultsController: NSObject, FetchedResultsControllerProtocol { +public class FetchedResultsController: NSObject, FetchedResultsControllerProtocol, @unchecked Sendable { public typealias Delegate = FetchedResultsControllerDelegate public typealias Section = FetchedResultsSection @@ -338,7 +341,9 @@ public class FetchedResultsController: NSObject, public extension FetchedResultsController { @MainActor - func performFetch(completion: @escaping @MainActor () -> Void) { + func performFetch( + completion: @escaping @MainActor @Sendable () -> Void + ) { startObservingNotificationsIfNeeded() definition.request { [weak self] objects in @@ -353,7 +358,7 @@ public extension FetchedResultsController { @MainActor func resort( using newSortDescriptors: [NSSortDescriptor], - completion: @escaping @MainActor () -> Void + completion: @escaping @MainActor @Sendable () -> Void ) { assert(Thread.isMainThread) @@ -555,7 +560,7 @@ private extension FetchedResultsController { updateFetchOrder: Bool = true, emitChanges: Bool = true, dropObjectsToInsert: Bool = true, - completion: @escaping @MainActor () -> Void + completion: @escaping @MainActor @Sendable () -> Void ) { assert(Thread.isMainThread) @@ -573,7 +578,7 @@ private extension FetchedResultsController { updateFetchOrder: Bool = true, emitChanges: Bool = true, dropObjectsToInsert: Bool = true, - completion: @escaping @MainActor () -> Void + completion: @escaping @MainActor @Sendable () -> Void ) { guard objects.count <= 100 || !Thread.isMainThread else { // Bounce ourself off of the main queue @@ -667,10 +672,10 @@ private extension FetchedResultsController { } @MainActor - func insert( + func insert( _ objects: C, emitChanges: Bool = true, - completion: @escaping @MainActor () -> Void + completion: @escaping @MainActor @Sendable () -> Void ) where C.Element == FetchedObject { // This is snapshotted because we're potentially about to be off the main thread let fetchedObjectIDs = self.fetchedObjectIDs @@ -705,11 +710,11 @@ private extension FetchedResultsController { return sortedObjects } - private func unsafeInsert( + private func unsafeInsert( _ objects: C, fetchedObjectIDs: OrderedSet, emitChanges: Bool = true, - completion: @escaping @MainActor () -> Void + completion: @escaping @MainActor @Sendable () -> Void ) where C.Element == FetchedObject { guard objects.count <= 100 || !Thread.isMainThread else { // Bounce ourself off of the main queue diff --git a/FetchRequests/Sources/Controller/FetchedResultsControllerProtocol.swift b/FetchRequests/Sources/Controller/FetchedResultsControllerProtocol.swift index 1f13774..e37f867 100644 --- a/FetchRequests/Sources/Controller/FetchedResultsControllerProtocol.swift +++ b/FetchRequests/Sources/Controller/FetchedResultsControllerProtocol.swift @@ -39,9 +39,14 @@ public protocol FetchedResultsControllerProtocol: DoublyObservabl var sortDescriptors: [NSSortDescriptor] { get } @MainActor - func performFetch(completion: @escaping @MainActor () -> Void) + func performFetch( + completion: @escaping @MainActor @Sendable () -> Void + ) @MainActor - func resort(using newSortDescriptors: [NSSortDescriptor], completion: @escaping @MainActor () -> Void) + func resort( + using newSortDescriptors: [NSSortDescriptor], + completion: @escaping @MainActor @Sendable () -> Void + ) @MainActor func reset() diff --git a/FetchRequests/Sources/Controller/PausableFetchedResultsController.swift b/FetchRequests/Sources/Controller/PausableFetchedResultsController.swift index ecce1fa..5c1ea0c 100644 --- a/FetchRequests/Sources/Controller/PausableFetchedResultsController.swift +++ b/FetchRequests/Sources/Controller/PausableFetchedResultsController.swift @@ -127,12 +127,17 @@ public class PausableFetchedResultsController { extension PausableFetchedResultsController: FetchedResultsControllerProtocol { @MainActor - public func performFetch(completion: @escaping @MainActor () -> Void) { + public func performFetch( + completion: @escaping @MainActor @Sendable () -> Void + ) { controller.performFetch(completion: completion) } @MainActor - public func resort(using newSortDescriptors: [NSSortDescriptor], completion: @escaping @MainActor () -> Void) { + public func resort( + using newSortDescriptors: [NSSortDescriptor], + completion: @escaping @MainActor @Sendable () -> Void + ) { controller.resort(using: newSortDescriptors, completion: completion) } diff --git a/FetchRequests/Sources/FetchableObject.swift b/FetchRequests/Sources/FetchableObject.swift index 91fc465..a5f5d94 100644 --- a/FetchRequests/Sources/FetchableObject.swift +++ b/FetchRequests/Sources/FetchableObject.swift @@ -23,7 +23,7 @@ public protocol RawDataRepresentable { } /// A class of types that should be fetchable via FetchRequests -public protocol FetchableObjectProtocol: NSObjectProtocol, Identifiable, RawDataRepresentable { +public protocol FetchableObjectProtocol: NSObjectProtocol, Identifiable, RawDataRepresentable, Sendable where ID: Sendable { /// Has this object been marked as deleted? var isDeleted: Bool { get }