Swift 6 Migration error in Sample code (Updating an app to use strict concurrency sample code) provided by Apple.

Updating an app to use strict concurrency is not compiling in Swift 6 with strict concurrency enabled. I am getting the following error in Xcode Version 16.0 (16A242d).

    private func queryHealthKit() async throws -> (
        [HKSample]?, [HKDeletedObject]?, HKQueryAnchor?
    ) {
        try await withCheckedThrowingContinuation { continuation in
            // Create a predicate that returns only samples created within the last 24 hours.
            let endDate = Date()
            let startDate = endDate.addingTimeInterval(-24.0 * 60.0 * 60.0)
            let datePredicate = HKQuery.predicateForSamples(
                withStart: startDate, end: endDate, options: [.strictStartDate, .strictEndDate])

            // Create the query.
            let query = HKAnchoredObjectQuery(
                type: caffeineType,
                predicate: datePredicate,
                anchor: anchor,
                limit: HKObjectQueryNoLimit
            ) { (_, samples, deletedSamples, newAnchor, error) in

                // When the query ends, check for errors.
                if let error {
                    continuation.resume(throwing: error)
                } else {
                    continuation.resume(returning: (samples, deletedSamples, newAnchor))
                }
            }
            store.execute(query)
        }
    }

The error is on
** continuation.resume(returning: (samples, deletedSamples, newAnchor)) ** and the error is

Task-isolated value of type '([HKSample]?, [HKDeletedObject]?, HKQueryAnchor?)' passed as a strongly transferred parameter; later accesses could race. How to solve this error?

Answered by DTS Engineer in 804338022

Just so we’re clear, we’re talking about the Updating an app to use strict concurrency sample code which is associated with WWDC 2024 Session 10169 Migrate your app to Swift 6.

When I build that with Xcode 16.0 I see the error you’re reporting. I think Xcode is correct here, and the sample is in error. To explore this, I hacked up the code to look like this:

private func queryHealthKit2() async throws -> HKSample {
    try await withCheckedThrowingContinuation { continuation in
        … unchanged …
    
        // Create the query.
        let query = HKAnchoredObjectQuery(
            type: caffeineType,
            predicate: datePredicate,
            anchor: anchor,
            limit: HKObjectQueryNoLimit
        ) { (_, samples, deletedSamples, newAnchor, error) in

            // When the query ends, check for errors.
            if let error {
                continuation.resume(throwing: error)
            } else {
                let s = samples!.first!
                continuation.resume(returning: s)
                         // ^ Sending 's' risks causing data races
                         // task-isolated 's' is passed as a 'sending' parameter; Uses in callee may race with later task-isolated uses
            }

        }
        store.execute(query)
    }
}

IMPORTANT This code isn’t meant to work! I hacked it up to uncover exactly what the compiler is complaining about. That’s why the method name is queryHealthKit2().

This gives a nicer error. The issue is that s is of type HKSample, which isn’t sendable. The value was created in one isolation domain (the query callback) and we’re trying to pass it to a different isolation domain (the queryHealthKit() async actor method).

Given that, I’d appreciate you filing a bug against the sample. Please post your bug number, just for the record.

As to what you can do about this, it depends on your goals. If you just want the sample to compile, so you can explore other parts of it, replace the problematic line with this:

continuation.resume(returning: (nil, nil, nil))

If you want the code to actually work, things get more complex. And it might be easier for us to discuss your real issue rather than this sample. Assuming that your really isn’t isn’t with HealthKit! (-:

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I'm getting the exact same error, very similar circumstances:

extension NSItemProvider {
    func loadObject<T>(ofClass: T.Type) async throws -> T? where T : _ObjectiveCBridgeable, T._ObjectiveCType : NSItemProviderReading {
        return try await withCheckedThrowingContinuation { continuation in
            
            _ = self.loadObject(ofClass: ofClass) { item, error in
                
                switch (item, error) {
                case (.some(let item), .none):
                    continuation.resume(returning: item) /* Task-isolated value of type 'T' passed as a strongly transferred parameter; later accesses could race; this is an error in the Swift 6 language mode */
                case (.none, .some(let error)):
                    continuation.resume(throwing: error)
                default:
                    let error = NSError(...)
                    continuation.resume(throwing: error)
                }
            }
        }
    }
}

Based on the advice below I changed the method signature to:

func loadObject<T>(ofClass: T.Type) async throws -> T? where T : _ObjectiveCBridgeable, T._ObjectiveCType : NSItemProviderReading, T: Sendable

which seems to have fixed it!

Just so we’re clear, we’re talking about the Updating an app to use strict concurrency sample code which is associated with WWDC 2024 Session 10169 Migrate your app to Swift 6.

When I build that with Xcode 16.0 I see the error you’re reporting. I think Xcode is correct here, and the sample is in error. To explore this, I hacked up the code to look like this:

private func queryHealthKit2() async throws -> HKSample {
    try await withCheckedThrowingContinuation { continuation in
        … unchanged …
    
        // Create the query.
        let query = HKAnchoredObjectQuery(
            type: caffeineType,
            predicate: datePredicate,
            anchor: anchor,
            limit: HKObjectQueryNoLimit
        ) { (_, samples, deletedSamples, newAnchor, error) in

            // When the query ends, check for errors.
            if let error {
                continuation.resume(throwing: error)
            } else {
                let s = samples!.first!
                continuation.resume(returning: s)
                         // ^ Sending 's' risks causing data races
                         // task-isolated 's' is passed as a 'sending' parameter; Uses in callee may race with later task-isolated uses
            }

        }
        store.execute(query)
    }
}

IMPORTANT This code isn’t meant to work! I hacked it up to uncover exactly what the compiler is complaining about. That’s why the method name is queryHealthKit2().

This gives a nicer error. The issue is that s is of type HKSample, which isn’t sendable. The value was created in one isolation domain (the query callback) and we’re trying to pass it to a different isolation domain (the queryHealthKit() async actor method).

Given that, I’d appreciate you filing a bug against the sample. Please post your bug number, just for the record.

As to what you can do about this, it depends on your goals. If you just want the sample to compile, so you can explore other parts of it, replace the problematic line with this:

continuation.resume(returning: (nil, nil, nil))

If you want the code to actually work, things get more complex. And it might be easier for us to discuss your real issue rather than this sample. Assuming that your really isn’t isn’t with HealthKit! (-:

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Swift 6 Migration error in Sample code (Updating an app to use strict concurrency sample code) provided by Apple.
 
 
Q