Meet async/await in Swift

RSS for tag

Discuss the WWDC21 session Meet async/await in Swift.

Posts under wwdc21-10132 tag

20 Posts

Post

Replies

Boosts

Views

Activity

How do you apply a diffable data source UI snapshot only after awaiting (with async/await) data fetched from the network?
I'm new to async/await, and am currently migrating my completion handler code to Swift 5.5's concurrency features. After generating an sync alternative in Xcode to my function func fetchMatchRecords(completion: @escaping ([Match]) -> Void), it becomes func fetchMatchRecords() async -> [Match]. I'm not sure how it would be used in the context of UIKit and diffable data sources. In a viewDidLoad, previously it would be MatchHistoryController.shared.fetchMatchRecords() { matches in DispatchQueue.main.async { self.dataSource.apply(self.initialSnapshot(), animatingDifferences: false) } } But I'm not sure how it would be used now Task { await MatchHistoryController.shared.fetchMatchRecords() } self.dataSource.apply(self.initialSnapshot(), animatingDifferences: false) How would I make sure that the snapshot is applied only after awaiting a successful fetch result? Here's the definition of initialSnapshot() that I used: func initialSnapshot() -> NSDiffableDataSourceSnapshot<Section, Match> { var snapshot = NSDiffableDataSourceSnapshot<Section, Match>() snapshot.appendSections([.main]) snapshot.appendItems(MatchHistoryController.shared.matches) return snapshot }
1
0
2.2k
Sep ’23
Canvas crashes with Task code
Good day! It seems to be a bug in Xcode that preview can be showed correctly with async code wrapped in Task, for ex: struct MyView: View { var onTapped: (() async -> Bool)? var body: some View { Button {             Task {                 guard await onTapped?() ?? true else { return }             } .....         } label: { Text("Tap me")         } } }      Crash log
2
0
1.2k
Apr ’22
Async/await and maxConcurrentOperationCount
I'm writing an app that performs actions in a web browser automatically on user's behalf. Currently my app uses OperationQueue to perform asynchronous work. I'm trying to rewrite the app to use async/await instead. Note, that it is necessary for my app to limit the number of concurrently executing work items. Otherwise the app may run into server throttling issues. However, I can't find an equivalent to OperationQueue's maxConcurrentOperationCount parameter in the new concurrency model. Is there a way to limit the number of concurrently running "lanes" of execution without resorting to using OperationQueue / DispatchQueue / NSLock ?
1
0
1.5k
Mar ’22
URLSessionWebSocketTask Crash
My app crashed when launch. The crash report: OS Version: iPhone OS 15.4 (19E5209h) Release Type: Beta Report Version: 104 Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Exception Note: EXC_CORPSE_NOTIFY Termination Reason: DYLD 4 Symbol missing Symbol not found: _$sSo25NSURLSessionWebSocketTaskC10FoundationE4sendyyAbCE7MessageOYaKF Referenced from: /private/var/containers/Bundle/Application/43FB5827-DE90-4FCF-A716-11A7FD5BE11E/Kingbox.app/Kingbox Expected in: /usr/lib/swift/libswiftFoundation.dylib (terminated at launch; ignore backtrace) Triggered by Thread: 0 Thread 0 Crashed: 0 dyld 0x00000001056506d0 __abort_with_payload + 8 1 dyld 0x00000001056562c8 abort_with_payload_wrapper_internal + 104 (terminate_with_reason.c:102) 2 dyld 0x00000001056562fc abort_with_payload + 16 (terminate_with_reason.c:124) 3 dyld 0x00000001056267e8 dyld4::halt(char const*) + 328 (DyldProcessConfig.cpp:2067) 4 dyld 0x0000000105623920 dyld4::prepare(dyld4::APIs&amp;, dyld3::MachOAnalyzer const*) + 3560 (dyldMain.cpp:0) 5 dyld 0x0000000105621c84 start + 488 (dyldMain.cpp:864) Demangle the symbol: _$sSo25NSURLSessionWebSocketTaskC10FoundationE4sendyyAbCE7MessageOYaKF (extension in Foundation):__C.NSURLSessionWebSocketTask.send((extension in Foundation):__C.NSURLSessionWebSocketTask.Message) async throws -&gt; ()
5
0
1.9k
Mar ’22
Swift 5.5 Task { ... } weak self
When using Task { ... } in Swift 5.5, I'm unclear if retain cycles might be an issue or not. For example: class ViewController: UIViewController { private var rows = [String]() private var tableView: UITableView? func populateRows() { Task { rows = (try? await getRowsFromNetwork()) ?? [] tableView?.reloadData() } } } Will populateRows retain the view controller for the life of the task because it references rows and tableView? If the view controller goes out of scope, I'd like it to have the freedom to deallocate without populateRows retaining it. This syntax compiles, but I don't know if it makes sense: class ViewController: UIViewController { private var rows = [String]() private var tableView: UITableView? func populateRows() { Task { [weak self] in self?.rows = (try? await self?.getRowsFromNetwork()) ?? [] self?.tableView?.reloadData() } } } I don't mind if the task continues to run. (I'm not worried about canceling it.) I just want to understand if there is a way to avoid retaining the view controller in the task, and if that happens automatically or if something like [weak self] is needed.
1
0
7.2k
Mar ’22
setting a variable on main thread
Hi, when working with SwiftUI @Published variables need to be set from the main thread, but at the same time, cannot be defined as @MainActor. The easy solution is a simple forced sync or async execution on the main thread, but it seems like this does not exist in the world of async/await and Tasks - at least I did not find it. Instead I found that all demo's from Apple is a quite sad solution. The full method is marked as @MainActor even though this is often only relevant for the last line. The question is either that I can execute a setter on main only OR that I can mark my SwiftUI code as being on main and thus being able to accept @MainActor @Published Is there really no solution? If so where do I have to propose/request a solution for this. I feel like every developer had written his own version of Thread.performOnMain, but here I want something using Task and that the compiler can verify. All the best Christoph
1
0
2.3k
Feb ’22
[async/await] The order matters for concurrent bindings with a tuple syntax
For the following example I'm expecting if one of the concurrent tasks has thrown an error, the rest unfinished tasks must be cancelled. But it isn't what I see. If task2 has thrown first, the task1 will continue execution till completion. But it works as expecting in vice-verse, failing task1 first, results task2 cancellation. The log in case if task2 has thrown first: task1 BEGIN task2 BEGIN task2 completed task2 catch CancellationError() task2 END task1 completed // It's not expecting to see this log task1 catch CancellationError() task1 END Failed: CancellationError() The log in case if task1 has thrown first (works as expected, see there is no 'task2 completed' log. As soon as task1 has thrown, the entire try await(,) throws as well.): task1 BEGIN task2 BEGIN task1 completed task1 catch CancellationError() task1 END Failed: CancellationError() task2 catch CancellationError() task2 END Code is below: async let t1 = task1() async let t2 = task2() do { _ = try await (t1, t2) } catch { print("Failed: \(error)") } func task1() async throws -> Int {     print("task1 BEGIN")     defer { print("task1 END") }     do {       try await Task.sleep(nanoseconds: UInt64(3 * 1_000_000_000))       print("task1 completed")       throw CancellationError()     } catch {       print("task1 catch \(error)")       throw error     } } func task2() async throws -> Int {     print("task2 BEGIN")     defer { print("task2 END") }     do {       try await Task.sleep(nanoseconds: UInt64(1 * 1_000_000_000))       print("task2 completed")       throw CancellationError()     } catch {       print("task2 catch \(error)")       throw error     } }
0
0
891
Feb ’22
Async @objc didPullToRefresh selector crashes app swift 5.5
I have a table to which I've added a refreshControl and when I pull down the table to refresh the data, I reset the array that feeds the table with data and then immediately request new data through an API call. Until now, I have used completion handlers and protocols to get the data into the table view but I want to move the logic to async/await because of the complexity needed by the network calls and the pyramid of nested closures. Populating the view in viewDidLoad works fine but with pullToRefresh selector I get an error: Thread 1: EXC_BAD_ACCESS (code=1, address=0xbcf917df8160) override func viewDidLoad() {     super.viewDidLoad()     setupView()     setupTableView()     setupTableRefreshControl()     Task {       await getBalances() //async network call       myTable.reloadData()     }   }    func setupTableRefreshControl() {     myTable.refreshControl = UIRefreshControl()     myTable.refreshControl?.addTarget(self, action: #selector(didPullToRefresh), for: .valueChanged)   } Code that crashes app:    @objc func didPullToRefresh() async {     balance.reset() // reset array to []     Task {       await getBalances() //async network call       myTable.reloadData()     }   }
1
0
969
Feb ’22
A big problem with Xcode13.3 and swiftui
After I updated xcode to 13.3 version, almost all mt spm project warns. SourcePackages/checkouts/SwiftUI-MediaPicker/SwiftUI.UIViewControllerRepresentable:7:24: Static method '_makeView(view:inputs:)' isolated to global actor 'MainActor' can not satisfy corresponding requirement from protocol 'View' It's pretty bad, because I don' wanna any warnings.
3
0
2.2k
Feb ’22
Apple CloudKit async function Doesn't Look Right
The function in question is the following. func records(for ids: [CKRecord.ID], desiredKeys: [CKRecord.FieldKey]? = nil) async throws -> [CKRecord.ID : Result<CKRecord, Error>] Note that the returned value looks like a dictionary of the form [CKRecord.ID : Result<CKRecord, Error>], but the input is an array of CKRecord.IDs. There are similar functions, but they return a tuple. Like the below example. func records(matching query: CKQuery, inZoneWith zoneID: CKRecordZone.ID? = nil, desiredKeys: [CKRecord.FieldKey]? = nil, resultsLimit: Int = CKQueryOperation.maximumResults) async throws -> (matchResults: [(CKRecord.ID, Result<CKRecord, Error>)], queryCursor: CKQueryOperation.Cursor?) Note that matchedResults is an array of tuples consisting of [(CKRecord.ID, Result<CKRecord, Error>)]. I would have thought that the return type in the first function would also be of the form [(CKRecord.ID, Result<CKRecord, Error>)]. What am I missing?
1
0
1.4k
Jan ’22
I'm unable to use the withTaskCancellaionHandler without a static analysis error
Hi, We have an API that I'm trying to prototype some async await extensions for. Most of our asynchronous methods are cancelable by returning an object that implements our AGSCancelable protocol that includes a cancel() method. Here's the code I have to try to extend a geocoding method on our AGSLocatorTask class: extension AGSLocatorTask { func geocode(withSearchText text: String) async throws -> [AGSGeocodeResult] { typealias GeocodeContinuation = CheckedContinuation<[AGSGeocodeResult], Error> var cancelable: AGSCancelable? return try await withTaskCancellationHandler(handler: { cancelable?.cancel() }, operation: { return try await withCheckedThrowingContinuation({ (continuation: GeocodeContinuation) in cancelable = self.geocode(withSearchText: text) { results, error in if let error = error { continuation.resume(throwing: error) } else { continuation.resume(returning: results!) } } }) }) } } This works great, but I have to comment out the cancelable?.cancel() call or else I get a Reference to captured var 'cancelable' in concurrently-executing code static analysis error (see attached screenshot). Could someone explain how to fix this, or is this a bug in the Xcode beta? Many thanks, and thanks for a great WWDC!!
4
0
1.8k
Dec ’21
Call async function on main actor from synchronous context
I am trying to understand as to why following piece of code throws an assertion. What I am trying to do is to call asyncFunc() on main thread/main actor from call site. I don't want to decorate asyncFunc with @MainActor as I want the function to be thread agnostic. func asyncFunc() async -> String? { dispatchPrecondition(condition: .onQueue(.main)) return "abc" } func callSite() { Task { @MainActor in await asyncFunc() } } My understanding was that Task { @MainActor ...} would execute all the following code on MainActor/main thread.
0
0
835
Dec ’21
Async and Await code doesn't work on command line tools but works on Xcode playgrounds
I am running Mac OS 12.1 and Xcode 13.2. My code is the following: import Foundation import Cocoa func trapezoid(_ begin: Double, _ end: Double,_ n: Int) async -> Double { let hc = (end-begin)/Double(n) var h = begin var result = 0.0 for _ in 0...n{ result += h*h + (h+hc)*(h+hc) h = h+hc } return result * (hc/2) } Task{ let answer1 = await trapezoid(0, 1, 10000) let answer2 = await trapezoid(1, 2, 10000) print(answer1) print(answer2) } With playgrounds I get the following correct result: 0.33343334500044286 2.333733355000306 However, when I use the exact same code in an Xcode project using Command Line Tools, the program just returns with exit code 0 and no output. I am not sure what my error is or if it is an Xcode bug.
2
0
2.1k
Dec ’21
New async await CloudKit Methods - What do you think?
Anybody converting from CKQueryOperation to the new CloudKit async await methods? If so, what do you think? I'm currently playing with func records(matching query: CKQuery, inZoneWith zoneID: CKRecordZone.ID? = nil, desiredKeys: [CKRecord.FieldKey]? = nil, resultsLimit: Int = CKQueryOperation.maximumResults) async throws -> (matchResults: [(CKRecord.ID, Result<CKRecord, Error>)], queryCursor: CKQueryOperation.Cursor?) and func records(continuingMatchFrom queryCursor: CKQueryOperation.Cursor, desiredKeys: [CKRecord.FieldKey]? = nil, resultsLimit: Int = CKQueryOperation.maximumResults) async throws -> (matchResults: [(CKRecord.ID, Result<CKRecord, Error>)], queryCursor: CKQueryOperation.Cursor?) They seem to work fine and eliminate completion handlers.
0
0
1.7k
Nov ’21
Async/let producing error in playground? Xcode 13.0 beta
I'm seeing an error trying to test out async let. It seems like this should work, based on the async/let and structured concurrency session videos. Here's the code: func doIt() async -> String {     let t = TimeInterval.random(in: 0.25 ... 2.0)     Thread.sleep(forTimeInterval: t)     return String("\(Double.random(in: 0...1000))") } async {     async let a = doIt()     async let b = doIt()     async let c = doIt()     async let d = doIt()     let results = await [a, b, c, d]     for result in results {         print("  \(result)")     } } But, I get this error for every "async let" statement: error: AsyncLetSwift55WWDC21.playground:12:15: error: expression is 'async' but is not marked with 'await' async let a = doIt() ^ await Am I missing something key, or is this a bug? I'm running this in the Xcode 13.0 beta, in a Playground. Thanks!!
12
0
4.4k
Aug ’21
Using async from SwiftUI
In "Meet async/await in Swift", around 23.38, we see that we in SwiftUI can do a .onAppear { async { self.image = try? await self.viewModel.fetchThumbnail(for: post.id) } } However, we also hear in this session that an async function can be called on one thread and resumed on another. In the code above, we update UI state, and thus self.image must be updated on the main thread. What on this slide ensures that it is actually returned to the main thread?
1
0
2.5k
Jun ’21
How do you apply a diffable data source UI snapshot only after awaiting (with async/await) data fetched from the network?
I'm new to async/await, and am currently migrating my completion handler code to Swift 5.5's concurrency features. After generating an sync alternative in Xcode to my function func fetchMatchRecords(completion: @escaping ([Match]) -> Void), it becomes func fetchMatchRecords() async -> [Match]. I'm not sure how it would be used in the context of UIKit and diffable data sources. In a viewDidLoad, previously it would be MatchHistoryController.shared.fetchMatchRecords() { matches in DispatchQueue.main.async { self.dataSource.apply(self.initialSnapshot(), animatingDifferences: false) } } But I'm not sure how it would be used now Task { await MatchHistoryController.shared.fetchMatchRecords() } self.dataSource.apply(self.initialSnapshot(), animatingDifferences: false) How would I make sure that the snapshot is applied only after awaiting a successful fetch result? Here's the definition of initialSnapshot() that I used: func initialSnapshot() -> NSDiffableDataSourceSnapshot<Section, Match> { var snapshot = NSDiffableDataSourceSnapshot<Section, Match>() snapshot.appendSections([.main]) snapshot.appendItems(MatchHistoryController.shared.matches) return snapshot }
Replies
1
Boosts
0
Views
2.2k
Activity
Sep ’23
Canvas crashes with Task code
Good day! It seems to be a bug in Xcode that preview can be showed correctly with async code wrapped in Task, for ex: struct MyView: View { var onTapped: (() async -> Bool)? var body: some View { Button {             Task {                 guard await onTapped?() ?? true else { return }             } .....         } label: { Text("Tap me")         } } }      Crash log
Replies
2
Boosts
0
Views
1.2k
Activity
Apr ’22
Async/await and maxConcurrentOperationCount
I'm writing an app that performs actions in a web browser automatically on user's behalf. Currently my app uses OperationQueue to perform asynchronous work. I'm trying to rewrite the app to use async/await instead. Note, that it is necessary for my app to limit the number of concurrently executing work items. Otherwise the app may run into server throttling issues. However, I can't find an equivalent to OperationQueue's maxConcurrentOperationCount parameter in the new concurrency model. Is there a way to limit the number of concurrently running "lanes" of execution without resorting to using OperationQueue / DispatchQueue / NSLock ?
Replies
1
Boosts
0
Views
1.5k
Activity
Mar ’22
await call in didSet block
How can we call async functions in did set blocks? This code will trigger a compilation error: 'didSet' accessor cannot have specifier 'async' @Published var lastLocation: CLLocation? { didSet async { await pinPosition() } }
Replies
2
Boosts
0
Views
2.9k
Activity
Mar ’22
URLSessionWebSocketTask Crash
My app crashed when launch. The crash report: OS Version: iPhone OS 15.4 (19E5209h) Release Type: Beta Report Version: 104 Exception Type: EXC_CRASH (SIGABRT) Exception Codes: 0x0000000000000000, 0x0000000000000000 Exception Note: EXC_CORPSE_NOTIFY Termination Reason: DYLD 4 Symbol missing Symbol not found: _$sSo25NSURLSessionWebSocketTaskC10FoundationE4sendyyAbCE7MessageOYaKF Referenced from: /private/var/containers/Bundle/Application/43FB5827-DE90-4FCF-A716-11A7FD5BE11E/Kingbox.app/Kingbox Expected in: /usr/lib/swift/libswiftFoundation.dylib (terminated at launch; ignore backtrace) Triggered by Thread: 0 Thread 0 Crashed: 0 dyld 0x00000001056506d0 __abort_with_payload + 8 1 dyld 0x00000001056562c8 abort_with_payload_wrapper_internal + 104 (terminate_with_reason.c:102) 2 dyld 0x00000001056562fc abort_with_payload + 16 (terminate_with_reason.c:124) 3 dyld 0x00000001056267e8 dyld4::halt(char const*) + 328 (DyldProcessConfig.cpp:2067) 4 dyld 0x0000000105623920 dyld4::prepare(dyld4::APIs&amp;, dyld3::MachOAnalyzer const*) + 3560 (dyldMain.cpp:0) 5 dyld 0x0000000105621c84 start + 488 (dyldMain.cpp:864) Demangle the symbol: _$sSo25NSURLSessionWebSocketTaskC10FoundationE4sendyyAbCE7MessageOYaKF (extension in Foundation):__C.NSURLSessionWebSocketTask.send((extension in Foundation):__C.NSURLSessionWebSocketTask.Message) async throws -&gt; ()
Replies
5
Boosts
0
Views
1.9k
Activity
Mar ’22
Swift 5.5 Task { ... } weak self
When using Task { ... } in Swift 5.5, I'm unclear if retain cycles might be an issue or not. For example: class ViewController: UIViewController { private var rows = [String]() private var tableView: UITableView? func populateRows() { Task { rows = (try? await getRowsFromNetwork()) ?? [] tableView?.reloadData() } } } Will populateRows retain the view controller for the life of the task because it references rows and tableView? If the view controller goes out of scope, I'd like it to have the freedom to deallocate without populateRows retaining it. This syntax compiles, but I don't know if it makes sense: class ViewController: UIViewController { private var rows = [String]() private var tableView: UITableView? func populateRows() { Task { [weak self] in self?.rows = (try? await self?.getRowsFromNetwork()) ?? [] self?.tableView?.reloadData() } } } I don't mind if the task continues to run. (I'm not worried about canceling it.) I just want to understand if there is a way to avoid retaining the view controller in the task, and if that happens automatically or if something like [weak self] is needed.
Replies
1
Boosts
0
Views
7.2k
Activity
Mar ’22
setting a variable on main thread
Hi, when working with SwiftUI @Published variables need to be set from the main thread, but at the same time, cannot be defined as @MainActor. The easy solution is a simple forced sync or async execution on the main thread, but it seems like this does not exist in the world of async/await and Tasks - at least I did not find it. Instead I found that all demo's from Apple is a quite sad solution. The full method is marked as @MainActor even though this is often only relevant for the last line. The question is either that I can execute a setter on main only OR that I can mark my SwiftUI code as being on main and thus being able to accept @MainActor @Published Is there really no solution? If so where do I have to propose/request a solution for this. I feel like every developer had written his own version of Thread.performOnMain, but here I want something using Task and that the compiler can verify. All the best Christoph
Replies
1
Boosts
0
Views
2.3k
Activity
Feb ’22
[async/await] The order matters for concurrent bindings with a tuple syntax
For the following example I'm expecting if one of the concurrent tasks has thrown an error, the rest unfinished tasks must be cancelled. But it isn't what I see. If task2 has thrown first, the task1 will continue execution till completion. But it works as expecting in vice-verse, failing task1 first, results task2 cancellation. The log in case if task2 has thrown first: task1 BEGIN task2 BEGIN task2 completed task2 catch CancellationError() task2 END task1 completed // It's not expecting to see this log task1 catch CancellationError() task1 END Failed: CancellationError() The log in case if task1 has thrown first (works as expected, see there is no 'task2 completed' log. As soon as task1 has thrown, the entire try await(,) throws as well.): task1 BEGIN task2 BEGIN task1 completed task1 catch CancellationError() task1 END Failed: CancellationError() task2 catch CancellationError() task2 END Code is below: async let t1 = task1() async let t2 = task2() do { _ = try await (t1, t2) } catch { print("Failed: \(error)") } func task1() async throws -> Int {     print("task1 BEGIN")     defer { print("task1 END") }     do {       try await Task.sleep(nanoseconds: UInt64(3 * 1_000_000_000))       print("task1 completed")       throw CancellationError()     } catch {       print("task1 catch \(error)")       throw error     } } func task2() async throws -> Int {     print("task2 BEGIN")     defer { print("task2 END") }     do {       try await Task.sleep(nanoseconds: UInt64(1 * 1_000_000_000))       print("task2 completed")       throw CancellationError()     } catch {       print("task2 catch \(error)")       throw error     } }
Replies
0
Boosts
0
Views
891
Activity
Feb ’22
Can I use async/await under iOS15.0?
As I can see, all the async APIs in XCode13.0 beta requires a deployment target of iOS 15.0, is that means that I cannot use async/await under iOS 15.0?
Replies
4
Boosts
0
Views
15k
Activity
Feb ’22
Async @objc didPullToRefresh selector crashes app swift 5.5
I have a table to which I've added a refreshControl and when I pull down the table to refresh the data, I reset the array that feeds the table with data and then immediately request new data through an API call. Until now, I have used completion handlers and protocols to get the data into the table view but I want to move the logic to async/await because of the complexity needed by the network calls and the pyramid of nested closures. Populating the view in viewDidLoad works fine but with pullToRefresh selector I get an error: Thread 1: EXC_BAD_ACCESS (code=1, address=0xbcf917df8160) override func viewDidLoad() {     super.viewDidLoad()     setupView()     setupTableView()     setupTableRefreshControl()     Task {       await getBalances() //async network call       myTable.reloadData()     }   }    func setupTableRefreshControl() {     myTable.refreshControl = UIRefreshControl()     myTable.refreshControl?.addTarget(self, action: #selector(didPullToRefresh), for: .valueChanged)   } Code that crashes app:    @objc func didPullToRefresh() async {     balance.reset() // reset array to []     Task {       await getBalances() //async network call       myTable.reloadData()     }   }
Replies
1
Boosts
0
Views
969
Activity
Feb ’22
A big problem with Xcode13.3 and swiftui
After I updated xcode to 13.3 version, almost all mt spm project warns. SourcePackages/checkouts/SwiftUI-MediaPicker/SwiftUI.UIViewControllerRepresentable:7:24: Static method '_makeView(view:inputs:)' isolated to global actor 'MainActor' can not satisfy corresponding requirement from protocol 'View' It's pretty bad, because I don' wanna any warnings.
Replies
3
Boosts
0
Views
2.2k
Activity
Feb ’22
Apple CloudKit async function Doesn't Look Right
The function in question is the following. func records(for ids: [CKRecord.ID], desiredKeys: [CKRecord.FieldKey]? = nil) async throws -> [CKRecord.ID : Result<CKRecord, Error>] Note that the returned value looks like a dictionary of the form [CKRecord.ID : Result<CKRecord, Error>], but the input is an array of CKRecord.IDs. There are similar functions, but they return a tuple. Like the below example. func records(matching query: CKQuery, inZoneWith zoneID: CKRecordZone.ID? = nil, desiredKeys: [CKRecord.FieldKey]? = nil, resultsLimit: Int = CKQueryOperation.maximumResults) async throws -> (matchResults: [(CKRecord.ID, Result<CKRecord, Error>)], queryCursor: CKQueryOperation.Cursor?) Note that matchedResults is an array of tuples consisting of [(CKRecord.ID, Result<CKRecord, Error>)]. I would have thought that the return type in the first function would also be of the form [(CKRecord.ID, Result<CKRecord, Error>)]. What am I missing?
Replies
1
Boosts
0
Views
1.4k
Activity
Jan ’22
I'm unable to use the withTaskCancellaionHandler without a static analysis error
Hi, We have an API that I'm trying to prototype some async await extensions for. Most of our asynchronous methods are cancelable by returning an object that implements our AGSCancelable protocol that includes a cancel() method. Here's the code I have to try to extend a geocoding method on our AGSLocatorTask class: extension AGSLocatorTask { func geocode(withSearchText text: String) async throws -> [AGSGeocodeResult] { typealias GeocodeContinuation = CheckedContinuation<[AGSGeocodeResult], Error> var cancelable: AGSCancelable? return try await withTaskCancellationHandler(handler: { cancelable?.cancel() }, operation: { return try await withCheckedThrowingContinuation({ (continuation: GeocodeContinuation) in cancelable = self.geocode(withSearchText: text) { results, error in if let error = error { continuation.resume(throwing: error) } else { continuation.resume(returning: results!) } } }) }) } } This works great, but I have to comment out the cancelable?.cancel() call or else I get a Reference to captured var 'cancelable' in concurrently-executing code static analysis error (see attached screenshot). Could someone explain how to fix this, or is this a bug in the Xcode beta? Many thanks, and thanks for a great WWDC!!
Replies
4
Boosts
0
Views
1.8k
Activity
Dec ’21
Call async function on main actor from synchronous context
I am trying to understand as to why following piece of code throws an assertion. What I am trying to do is to call asyncFunc() on main thread/main actor from call site. I don't want to decorate asyncFunc with @MainActor as I want the function to be thread agnostic. func asyncFunc() async -> String? { dispatchPrecondition(condition: .onQueue(.main)) return "abc" } func callSite() { Task { @MainActor in await asyncFunc() } } My understanding was that Task { @MainActor ...} would execute all the following code on MainActor/main thread.
Replies
0
Boosts
0
Views
835
Activity
Dec ’21
Async and Await code doesn't work on command line tools but works on Xcode playgrounds
I am running Mac OS 12.1 and Xcode 13.2. My code is the following: import Foundation import Cocoa func trapezoid(_ begin: Double, _ end: Double,_ n: Int) async -> Double { let hc = (end-begin)/Double(n) var h = begin var result = 0.0 for _ in 0...n{ result += h*h + (h+hc)*(h+hc) h = h+hc } return result * (hc/2) } Task{ let answer1 = await trapezoid(0, 1, 10000) let answer2 = await trapezoid(1, 2, 10000) print(answer1) print(answer2) } With playgrounds I get the following correct result: 0.33343334500044286 2.333733355000306 However, when I use the exact same code in an Xcode project using Command Line Tools, the program just returns with exit code 0 and no output. I am not sure what my error is or if it is an Xcode bug.
Replies
2
Boosts
0
Views
2.1k
Activity
Dec ’21
New async await CloudKit Methods - What do you think?
Anybody converting from CKQueryOperation to the new CloudKit async await methods? If so, what do you think? I'm currently playing with func records(matching query: CKQuery, inZoneWith zoneID: CKRecordZone.ID? = nil, desiredKeys: [CKRecord.FieldKey]? = nil, resultsLimit: Int = CKQueryOperation.maximumResults) async throws -> (matchResults: [(CKRecord.ID, Result<CKRecord, Error>)], queryCursor: CKQueryOperation.Cursor?) and func records(continuingMatchFrom queryCursor: CKQueryOperation.Cursor, desiredKeys: [CKRecord.FieldKey]? = nil, resultsLimit: Int = CKQueryOperation.maximumResults) async throws -> (matchResults: [(CKRecord.ID, Result<CKRecord, Error>)], queryCursor: CKQueryOperation.Cursor?) They seem to work fine and eliminate completion handlers.
Replies
0
Boosts
0
Views
1.7k
Activity
Nov ’21
Async await backword support issue
Can we use async await on under iOS 15?
Replies
1
Boosts
0
Views
1.5k
Activity
Nov ’21
Async/let producing error in playground? Xcode 13.0 beta
I'm seeing an error trying to test out async let. It seems like this should work, based on the async/let and structured concurrency session videos. Here's the code: func doIt() async -> String {     let t = TimeInterval.random(in: 0.25 ... 2.0)     Thread.sleep(forTimeInterval: t)     return String("\(Double.random(in: 0...1000))") } async {     async let a = doIt()     async let b = doIt()     async let c = doIt()     async let d = doIt()     let results = await [a, b, c, d]     for result in results {         print("  \(result)")     } } But, I get this error for every "async let" statement: error: AsyncLetSwift55WWDC21.playground:12:15: error: expression is 'async' but is not marked with 'await' async let a = doIt() ^ await Am I missing something key, or is this a bug? I'm running this in the Xcode 13.0 beta, in a Playground. Thanks!!
Replies
12
Boosts
0
Views
4.4k
Activity
Aug ’21
var tasks = Set<Task.Handle<Void, Never>>()
New error in XCode 13 Beta 4: "Generic parameter 'Success' could not be inferred" No error in earlier XCode 13 Beta. What's the fix? THe above line is from Apple example code: "DrawTogether"
Replies
1
Boosts
0
Views
1.1k
Activity
Aug ’21
Using async from SwiftUI
In "Meet async/await in Swift", around 23.38, we see that we in SwiftUI can do a .onAppear { async { self.image = try? await self.viewModel.fetchThumbnail(for: post.id) } } However, we also hear in this session that an async function can be called on one thread and resumed on another. In the code above, we update UI state, and thus self.image must be updated on the main thread. What on this slide ensures that it is actually returned to the main thread?
Replies
1
Boosts
0
Views
2.5k
Activity
Jun ’21