Concurrency

RSS for tag

Concurrency is the notion of multiple things happening at the same time.

Pinned Posts

Posts under Concurrency tag

89 Posts
Sort by:
Post marked as solved
3 Replies
887 Views
Hello! I'm developing a SDK and a customer is experiencing a very rare crash (happening for < 10 users) for which there are no clear repro steps. In the attached backtrace of the crash, there are two threads #13 and #17 which seem to be accessing the same part of the code (named MyMethod2 in the file). Thread #17 is the one crashing during deallocation of some protobuf objects. We designed MyMethod2 to be called by at most one thread at any point in time by using a serial DispatchQueue. My question is: can we tell for sure that the threads #13 and #17 shown in the file were executing that shared code simultaneously just by looking at the trace? If so, there'd be a concurrency bug in my code that I need to fix, but I haven't found anything suspicious. If on the other hand, these two threads were both used by the serial queue but at different times, then the problem is elsewhere. Thank you for your help! The two threads: Thread 13 name: Thread 13: 0 libsystem_kernel.dylib 0x00000001f61a0cb0 write (libsystem_kernel.dylib) 1 CoreFoundation 0x00000001aed14f68 fileWrite (CoreFoundation) 2 CoreFoundation 0x00000001aed14c40 CFWriteStreamWrite (CoreFoundation) 3 [MyHiddenAppName] 0x0000000107b81f8c NSOutputStream.write(_:) 4 [MyHiddenAppName] 0x0000000107ab6640 specialized MyMethod2 5 [MyHiddenAppName] 0x0000000107ab6cf0 partial apply for closure #1 in MyMethod1 6 [MyHiddenAppName] 0x0000000102ba0538 thunk for @escaping @callee_guaranteed () -> () (<compiler-generated>:0) 7 libdispatch.dylib 0x00000001b6c4f6a8 _dispatch_call_block_and_release (libdispatch.dylib) [...] Thread 17 name: Thread 17 Crashed: 0 libswiftCore.dylib 0x00000001a8467d70 _swift_release_dealloc (libswiftCore.dylib) 1 libswiftCore.dylib 0x00000001a8469424 bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1>>::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) (libswiftCore.dylib) 2 [MyHiddenAppName] 0x0000000107a45b54 destroy for MyProtoStruct4 3 [MyHiddenAppName] 0x0000000107a55c64 outlined destroy of (MyProtoStruct2.OneOfEnum, MyProtoStruct2.OneOfEnum) 4 [MyHiddenAppName] 0x0000000107a4503c MyProtoStruct4._StorageClass.__deallocating_deinit 5 libswiftCore.dylib 0x00000001a8467d88 _swift_release_dealloc (libswiftCore.dylib) 6 libswiftCore.dylib 0x00000001a8469424 bool swift::RefCounts<swift::RefCountBitsT<(swift::RefCountInlinedness)1>>::doDecrementSlow<(swift::PerformDeinit)1>(swift::RefCountBitsT<(swift::RefCountInlinedness)1>, unsigned int) (libswiftCore.dylib) 7 [MyHiddenAppName] 0x0000000107a6a91c destroy for MyProtoStruct3 [...] 80 [MyHiddenAppName] 0x0000000107ab6108 specialized MyMethod2 81 [MyHiddenAppName] 0x0000000107ab6cf0 partial apply for closure #1 in MyMethod1 82 [MyHiddenAppName] 0x0000000102ba0538 thunk for @escaping @callee_guaranteed () -> () (<compiler-generated>:0) 83 libdispatch.dylib 0x00000001b6c4f6a8 _dispatch_call_block_and_release (libdispatch.dylib) [...] crash_backtrace.txt
Posted Last updated
.
Post not yet marked as solved
2 Replies
1.1k Views
In my TestApp I run the following code, to calculate every pixel of a bitmap concurrently: private func generate() async {     for x in 0 ..< bitmap.width{         for y in 0 ..< bitmap.height{             let result = await Task.detached(priority:.userInitiated){                return iterate(x,y)             }.value             displayResult(result)         }     } } This works and does not give any warnings or runtime issues. After watching the WWDC talk "Visualize and optimize Swift concurrency" I used instruments to visualize the Tasks: The number of active tasks continuously raises until 2740 and stays constant at this value even after all 64000 pixels have been calculated and displayed. What am I doing wrong?
Posted Last updated
.
Post not yet marked as solved
0 Replies
387 Views
Hi, Despite the following code works great on Windows and Linux (well, there is an OS layer stripped from the code), it hangs on macOS (pseudocode first): create non-blocking socketpair(AF_UNIX, SOCK_STREAM, ...); + a couple of fcntl(fd, ..., flags | O_NONBLOCK) spawn 128 pairs of threads (might be as little as 32, but will need several iterations to reproduce). Of course, there is the errno check to ensure there are no errors but EWOULDBLOCK / EAGAIN readers read a byte 10000 times: for (...) { while (read(fd[1]...) < 1) select(...); r++;} writers write a byte 10000 times: for (...) { while (write(fd[0]...) < 1) select(...); w++;} Join writers; Join readers; On Linux/Windows with the iterations number really cranked up, I'm getting a socket buffer overflow, so ::write returns EWOULDBLOCK, then I'm waiting on a socket until it's ready, continue, and after joining both sets of threads I see that bytes-read is equal to bytes-written, everything fine. However, on macOS I quickly end up in a strange lock when writers are waiting on ::select(...., &write_fds, ...) and readers on the corresponding ::select(..., &read_fds, ...); I have really no idea how that could happen except that the read/write is not thread-safe. However, it looks like POSIX docs and manpages state that it is (at least, reentrant). Could anyone point me in the right direction? Detailed code below: std::atomic<int> bytes_written(0); std::atomic<int> bytes_read(0); static constexpr int k_packets = 10000; static constexpr int k_threads = 32; std::vector<std::thread> writers; std::vector<std::thread> readers; writers.reserve(k_threads); readers.reserve(k_threads); for (int i = 0; i < k_threads; ++i) { writers.emplace_back([fd_write = fd[1], &bytes_written]() { char data = 'x'; for (int i = 0; i < k_packets; ++i) { while (::write(fd_write, &data, 1) < 1) { fd_set writefds; FD_ZERO(&writefds); FD_SET(fd_write, &writefds); assert(errno == EAGAIN || errno == EWOULDBLOCK); int retval = ::select(fd_write + 1, nullptr, &writefds, nullptr, nullptr); if (retval < 1) assert(errno == EAGAIN || errno == EWOULDBLOCK); } ++bytes_written; } }); readers.emplace_back([fd_read = fd[0], &bytes_read]() { char data; for (int i = 0; i < k_packets; ++i) { while (::read(fd_read, &data, 1) < 1) { fd_set readfds; FD_ZERO(&readfds); FD_SET(fd_read, &readfds); assert(errno == EAGAIN || errno == EWOULDBLOCK); int retval = ::select(fd_read + 1, &readfds, nullptr, nullptr, nullptr); if (retval < 1) assert(errno == EAGAIN || errno == EWOULDBLOCK); } ++bytes_read; } }); } for (auto& t : writers) t.join(); for (auto& t : readers) t.join(); assert(bytes_written == bytes_read);
Posted Last updated
.
Post marked as solved
1 Replies
449 Views
I am trying to use code from Apple's sample project on StoreKit (Implementing a store in your app using the StoreKit API). However, even if I don't make any changes to this sample project except enable "complete" concurrency checking in the build settings, I get warnings like Capture of 'self' with non-sendable type 'Store' in a '@Sendable' closure. How worried should I be about these warnings and how can I fix them?
Posted
by grachus.
Last updated
.
Post not yet marked as solved
1 Replies
457 Views
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libicucore.A.dylib 0x18c500918 icu::SimpleDateFormat::subFormat(icu::UnicodeString&amp;, char16_t, int, UDisplayContext, int, char16_t, icu::FieldPositionHandler&amp;, icu::Calendar&amp;, UErrorCode&amp;) const + 532 1 libicucore.A.dylib 0x18c500520 icu::SimpleDateFormat::format(icu::Calendar&amp;, icu::UnicodeString&amp;, icu::FieldPositionHandler&amp;, UErrorCode&amp;) const + 520 2 libicucore.A.dylib 0x18c5002f8 icu::SimpleDateFormat::format(icu::Calendar&amp;, icu::UnicodeString&amp;, icu::FieldPosition&amp;) const + 84 3 libicucore.A.dylib 0x18c42c4ac icu::DateFormat::format(double, icu::UnicodeString&amp;, icu::FieldPosition&amp;) const + 176 4 libicucore.A.dylib 0x18c535c40 udat_format + 352 5 CoreFoundation 0x189349a14 __cficu_udat_format + 68 6 CoreFoundation 0x189349898 CFDateFormatterCreateStringWithAbsoluteTime + 192 7 Foundation 0x18a432bf0 -[NSDateFormatter stringForObjectValue:] + 316 8 ShiningUtiliesKit 0x10522a130 SULog.log(:logDegree:file:method:line:) + 488 9 ShiningUtiliesKit 0x105229f3c SULog.debug(:file:method:line:) + 48 10 Calibration 0x1029f56bc closure #1 in Device.setDeviceData(:) + 487 (DeviceObject.swift:293) 11 Calibration 0x1029f3de0 specialized autoreleasepool(invoking:) + 23 (:0) [inlined] 12 Calibration 0x1029f3de0 Device.setDeviceData(_:) + 23 (DeviceObject.swift:291) [inlined] 13 Calibration 0x1029f3de0 closure #1 in closure #1 in variable initialization expression of Device.callback + 403 (DeviceObject.swift:221) 14 Calibration 0x1029f3548 thunk for @escaping @callee_guaranteed () -&gt; () + 27 (:0) 15 libdispatch.dylib 0x18907dcb8 _dispatch_call_block_and_release + 32 16 libdispatch.dylib 0x18907f910 _dispatch_client_callout + 20 17 libdispatch.dylib 0x18908dfa8 _dispatch_main_queue_drain + 984 18 libdispatch.dylib 0x18908dbc0 _dispatch_main_queue_callback_4CF + 44 19 CoreFoundation 0x18934b15c CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE + 16 20 CoreFoundation 0x189308a80 __CFRunLoopRun + 1996 21 CoreFoundation 0x189307c5c CFRunLoopRunSpecific + 608 22 HIToolbox 0x193884448 RunCurrentEventLoopInMode + 292 23 HIToolbox 0x193884284 ReceiveNextEventCommon + 648 24 HIToolbox 0x193883fdc _BlockUntilNextEventMatchingListInModeWithFilter + 76 25 AppKit 0x18cae2c54 _DPSNextEvent + 660 26 AppKit 0x18d2b8ebc -[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 716 27 AppKit 0x18cad6100 -[NSApplication run] + 476 28 AppKit 0x18caad3cc NSApplicationMain + 880 29 SwiftUI 0x1b3c14f80 0x1b3b3b000 + 892800 30 SwiftUI 0x1b44a530c 0x1b3b3b000 + 9872140 31 SwiftUI 0x1b48eb4f0 0x1b3b3b000 + 14353648 32 Calibration 0x1029fa1a0 static IntraoralScanMiniProgramApp.$main() + 51 (IntraoralScanMiniProgramApp.swift:14) [inlined] 33 Calibration 0x1029fa1a0 main + 63 (DeviceObject.swift:0) 34 dyld 0x188eb10e0 start + 2360 My mac APP has a crash about DateFormatter. mac version is 14.1.1. public class SULog { private let dateFormatter = { let dateFormatter = DateFormatter() dateFormatter.dateFormte = "yyy-MM-dd HH:mm:ss_sss" return dateFormatter } private var lock = NSLock() public func debug(_ message: Any...) { log(message) } public func log(_ message: Any...) { lock.lock() let date = Date() let dateString = dateFormatter.string(from:date) lock.unlock() print(dateString) } } var log:SULog! class AppDelegate: NSObject { func applicationWillFinishLaunching(_ notification: Notification) { log = SULog() } } public class Test { func test() { autoreleasepool { //.......other code log.debug("test") // crashed //........ other code } } } Any thought on this crash? Thanks
Posted
by shuai liu.
Last updated
.
Post not yet marked as solved
1 Replies
410 Views
I am following the iOS App Dev Tutorials on Adopting Swift concurrency and Persisting data. On Adopting Swift concurrency, it is mentioned that we can call an asynchronous function using the await keyword. Because the asynchronous function can suspend execution, we can use await only in asynchronous contexts, such as inside the body of another asynchronous function. Adopting Swift concurrency, it is also mentioned that we can create a new asynchronous context with a Task to call asynchronous functions from a synchronous context. Based on this information, I concluded that the main added value of a Task is to enable calling an asynchronous function in a synchronous context. On Persisting data, a Task object is created inside the declaration block of an asynchronous function: func load() async throws { let task = Task<[DailyScrum], Error> { let fileURL = try Self.fileURL() guard let data = try? Data(contentsOf: fileURL) else { return [] } let dailyScrums = try JSONDecoder().decode([DailyScrum].self, from: data) return dailyScrums } let scrums = try await task.value self.scrums = scrums } I didn't understand why it was necessary to create task. Based on what I learned from Adopting Swift concurrency, the context of load() is already asynchronous. Therefore, we can simply call asynchronous functions without the need to create a Task object. When I tried to run the code by removing the task, the app still worked the same, or at least that was my perception. I believe that there is another reason to use Task in this example other than just enabling calling asynchronous functions. However, this was not explicitly explained in the tutorials. Could you please explain why we use Task here? What is the added value and how it would improve the behavior of this app? Please keep in mind that I am a complete beginner and had no idea about what concurrency was two weeks ago. In case deleting task would not change anything, could you please confirm that my initial understanding was correct?
Posted Last updated
.
Post not yet marked as solved
2 Replies
784 Views
How do I safely access Core data NSManagedObject attributes from SwiftUI view using the swift concurrency model. My understanding is we need to enclose any access to NSManageObject attributes in await context.perform {}. But if I use it anywhere in a view be that in the body(), or init() or .task() modifier I get the following warnings or errors: for .task{} modifier or if within any Task {}: Passing argument of non-sendable type 'NSManagedObjectContext.ScheduledTaskType' outside of main actor-isolated context may introduce data races this happens even if I create a new context solely for this access. if within body() or init(): 'await' in a function that does not support concurrency but we cant set body or init() to async an example of the code is something along the lines of: var attributeString: String = "" let context = PersistentStore.shared.persistentContainer.newBackgroundContext() await context.perform { attributeString = nsmanagedObject.attribute! }
Posted
by ngb.
Last updated
.
Post not yet marked as solved
0 Replies
519 Views
Swift Concurrency Resources: DevForums tags: Concurrency The Swift Programming Language Concurrency > Concurrency documentation WWDC 2022 Session 110351 Eliminate data races using Swift Concurrency — This ‘sailing on the sea of concurrency’ talk is a great introduction to the fundamentals. WWDC 2021 Session 10134 Explore structured concurrency in Swift — The table that starts rolling out at around 25:45 is really helpful. Dispatch Resources: DevForums tags: Dispatch Dispatch documentation — Note that the Swift API and C API, while generally aligned, are different in many details. Make sure you select the right language at the top of the page. Dispatch man pages — While the standard Dispatch documentation is good, you can still find some great tidbits in the man pages. See Reading UNIX Manual Pages. Start by reading dispatch in section 3. WWDC 2015 Session 718 Building Responsive and Efficient Apps with GCD [1] WWDC 2017 Session 706 Modernizing Grand Central Dispatch Usage [1] Avoid Dispatch Global Concurrent Queues DevForums post Share and Enjoy — Quinn “The Eskimo!” @ Developer Technical Support @ Apple let myEmail = "eskimo" + "1" + "@" + "apple.com" [1] These videos may or may not be available from Apple. If not, the URL should help you locate other sources of this info.
Posted
by eskimo.
Last updated
.
Post not yet marked as solved
0 Replies
372 Views
I use this function to read calendar headers in a array of strings: `func getCalendarHeaders(ofType: EKEntityType, alerter: Alerter) async -> [String] { var headers: [String] = [] do { if try await requestAuthorizationFor(ofType) { let calendars = try await fetchCalendars(ofType: ofType) for calendar in calendars { headers.append(calendar.title) } } } catch let error { DispatchQueue.main.async { alerter.alert = ErrorManager.shared.showAlert(error: error) } } return headers } In my view model / or view I try to init with: Task { self.eventCalendarHeaders = await CalendarManager.shared.getCalendarHeaders(ofType: EKEntityType.event, alerter: alerter) } Why I get this error? Trailing closure passed to parameter of type 'EKEvent?' that does not accept a closure
Posted
by Hemser.
Last updated
.
Post marked as solved
5 Replies
3.6k Views
Can't understand why this compiles extension HomeReducer { @MainActor @Observable final class State: BaseState { var isPresentingSubscription = false } } class BaseState {} but this gives an error Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context extension HomeReducer { @MainActor @Observable final class State { var isPresentingSubscription = false } } extension DependencyValues { var homeView: @Sendable () -> HomeView { HomeKey().value } private struct HomeKey: DependencyKey { typealias Value = @Sendable () -> HomeView let liveValue: Value = { HomeView(store: Store(initialState: HomeReducer.State(), reducer: HomeReducer())) } let testValue: Value = { fatalError("testValue not implemented") } var previewValue: Value = { fatalError("previewValue not implemented") } } }
Posted
by kmisiag.
Last updated
.
Post not yet marked as solved
0 Replies
506 Views
anyone know how to use the new swift concurrency model (ie. await context.perform and context.perform) core data willSave()? for example. how would I ensure this is thread safe? changing self.managedObjectContext!.performAndWait to await self.managedObjectContext!.perform means I have to change willSave() to async which then means it never gets called because its not overriding the correct method anymore. override public func willSave() { self.managedObjectContext!.performAndWait { if self.modifiedDate == nil || Date().timeIntervalSince(self.modifiedDate!) >= 1 { self.modifiedDate = Date() } } super.willSave() }
Posted
by ngb.
Last updated
.
Post not yet marked as solved
1 Replies
510 Views
I've been working with Swift Concurrency a good bit for about 6 months now and keep bumping into where I need to bridge synchronously between it and other nonisolated system frameworks. I'm curious if there are recommended patterns for this type of interaction. Consider this scenario: I have a @MainActor isolated class that I'm using in my UI and would like to make it Codable. As soon as you add that requirement, the init(from decoder: Decoder) and encode(to encoder Encoder) must each be nonisolated, synchronous calls, which as far as I can tell means that I need an inner lock (NSLock or similar) to guard access to the state of the class. Despite the claim made elsewhere in the forums it is not as simple as adding the async keyword to these methods because it changes their signature. While I agree it is the right thing to encode/decode in the background off the main thread, adding locks every time I need to bridge feels contrary to the spirit of Swift Concurrency. What am I missing?
Posted Last updated
.
Post not yet marked as solved
1 Replies
1.3k Views
Hey there, I have a problem running multiply tasks in parallel in a SwiftUI view. struct ModelsView: View { @StateObject var tasks = TasksViewModel() var body: some View { NavigationView{ ScrollView { ForEach(Array(zip(tasks.tasks.indices, tasks.tasks)), id: \.0) { task in NavigationLink(destination: ModelView()) { ModelPreviewView(model_name: "3dobject.usdz") .onAppear { if task.0 == tasks.tasks.count - 2 { Task { print(tasks.tasks.count) await tasks.fetch_tasks(count: 4) } } } } } }.navigationTitle("3D modelle") }.onAppear{ Task { await tasks.fetch_tasks(count: 5) await tasks.watch_for_new_tasks() } } } } In my view, I spawn a task as soon as the View Appears which, first, fetches 5 tasks from the database (this works fine), and then it starts watching for new tasks. In the Scroll View, right before the bottom is reached, I start loading new tasks. The problem is, the asynchronous function fetch_tasks(count: 4) only gets continued if the asynchronous function watch_for_new_tasks() stops blocking. actor TasksViewModel: ObservableObject { @MainActor @Published private(set) var tasks : [Tasks.Task] = [] private var last_fetched_id : String? = nil func fetch_tasks(count: UInt32) async { do { let tasks_data = try await RedisClient.shared.xrevrange(streamName: "tasks", end: last_fetched_id ?? "+" , start: "-", count: count) last_fetched_id = tasks_data.last?.id let fetched_tasks = tasks_data.compactMap { Tasks.Task(from: $0.data) } await MainActor.run { withAnimation(.easeInOut) { self.tasks.append(contentsOf: fetched_tasks) } } } catch { print("Error fetching taskss \(error)") } } func watch_for_new_tasks() async { while !Task.isCancelled { do { let tasks_data = try await RedisClient.shared.xread(streams: "tasks", ids: "$") let new_tasks = tasks_data.compactMap { Tasks.Task(from: $0.data) } await MainActor.run { for new_task in new_tasks.reversed() { withAnimation { self.tasks.insert(new_task, at: 0) } } } } catch { print(error) } } } ... } The asynchronous function watch_for_new_tasks() uses RedisClient.shared.xread(streams: "tasks", ids: "$") which blocks until at least one tasks is added to the Redis Stream. I tried running the watch_for_new_tasks() on a Task.detached tasks, but that also blocks. To be honest, I have no idea why this blocks, and I could use your guy's help if you could. Thank you in Advance, Michael
Posted
by Wikipedia.
Last updated
.
Post not yet marked as solved
1 Replies
2.4k Views
Hi, Xcode warns me that NSPersistentContainer, NSManagedObjectContext, NSPersistentHistoryTransaction and NSPersistentHistoryToken are non-Sendable types and therefore cannot cross actor boundaries. These warnings occur even when I use @preconcurrency import CoreData (only works with Xcode 14.0 Beta, in Xcode 13.4.1, it says '@preconcurrency' attribute on module 'CoreData' is unused) I understand that types in Core Data have yet to be marked as Sendable when it makes sense. Although NSPersistentHistoryTransaction, and NSPersistentHistoryToken are reference types, they should qualify to be marked as Sendable in the future since these are immutable types, am I right? NSPersistentContainer provides variables and methods like viewContext and newBackgroundContext(). It would make sense that this type is thread-safe. However, I'm not sure about it, especially regarding its loadPersistentStores(completionHandler:) method. Is NSPersistentContainer (and its subclass NSPersistentCloudKitContainer) thread-safe and should it be marked as Sendable in the future? The case of and NSManagedObjectContext confuses me the most. Indeed, it has both thread-safe methods like perform(_:) and thread-unsafe methods like save(). Still, it should be possible to cross actor boundaries. Would such a "partially thread-safe" type quality to be marked as Sendable? If not, how can it cross actor boundaries? The reason I'm asking these questions is that I have a CoreDataStack type. It has mutable variables, such as var lastHistoryToken: NSPersistentHistoryToken?, needs to perform work without blocking the main thread, such as writing the token to a file, has async methods, uses notification observers, and needs to be marked as Sendable to be used by other controllers running on different actors. Since this type is related to back-end work, I made it an Actor. This type exposes the persistent container, and a method to create new background threads. However, I need to explicitly annotate all methods using await context.perform { ... } as nonisolated in this actor. Not doing so causes a data race to be detected at runtime. Is this a bug, and is making a Core Data stack an Actor the proper way to do it or is there a better solution? Any help would be greatly appreciated. Thanks. Xcode Configuration Xcode 13.4.1, Xcode 14.0 beta 5 The Xcode project is configured with Other Swift Flags set to -Xfrontend -warn-concurrency -Xfrontend -enable-actor-data-race-checks.
Posted
by Romain.
Last updated
.
Post not yet marked as solved
5 Replies
588 Views
class CalculatorViewModel : NSObject, ObservableObject, Identifiable { var id = UUID() @Published var output = "Disconnected" @Published var connected = false @Published var databasePath = String() enum itemType : Int{ case angle = 1 case degree = 2 case grip1 = 3 case grip2 = 4 } struct test_Array: Identifiable { var id = UUID() var time: String var swingNum : Int var dataSeqInSwing: Int var timeStampInSeq: Double var itemType: Int var value: Double } @Published var testDBdata = [test_Array] () ..... private var centralManager: CBCentralManager? func connectCalculator() { output = "Connecting..." centralQueue = DispatchQueue(label: "test.discovery") centralManager = CBCentralManager(delegate: self, queue: centralQueue) } .... func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { ..... if characteristic.uuid == outputCharUUID, var data = characteristic.value { ..... DispatchQueue.main.async() { for index in tupleSets { strItemSets = index.components(separatedBy: ",") ....... var itemN = 1 for indexStr in strItemSets { self.golfDBdata[numDB].dataSeqInSwing = countItem. <= Error self.golfDBdata[numDB].itemType = itemN self.golfDBdata[numDB].value = Double(strItemSets[itemN]) ?? 0.0
Posted Last updated
.
Post marked as solved
4 Replies
817 Views
My request call site: let headers = coordinator.requestHeaders(path: headersPath) var request = URLRequest(url: url, cachePolicy: .useProtocolCachePolicy, timeoutInterval: defaultTimeoutInterval) request.httpMethod = HTTPRequestMethod.get.rawValue request.allHTTPHeaderFields = headers let delegate = SessionDelegate(priority: priority, progressHandler: progressHandler) let session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: .main) let (localUrl, response) = try await session.download(for: request) let data = try Data(contentsOf: localUrl) SessionDelegate: public class SessionDelegate: NSObject, URLSessionTaskDelegate, URLSessionDownloadDelegate { public typealias ProgressHandler = ((_ progress: Double) -&gt; Void) public var metrics: URLSessionTaskMetrics? private let priority: TaskPriority private let progressHandler: ProgressHandler? //MARK: - Lifecycle init(priority: TaskPriority, progressHandler: ProgressHandler? = nil) { self.priority = priority self.progressHandler = progressHandler } //MARK: - URLSessionTaskDelegate public func urlSession(_ session: URLSession, didCreateTask task: URLSessionTask) { task.priority = priority.rawValue } public func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) { self.metrics = metrics } public func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) { if let progressHandler { let progress = Progress(totalUnitCount: totalBytesExpectedToSend) progress.completedUnitCount = totalBytesSent progressHandler(progress.fractionCompleted) } } //MARK: - URLSessionDownloadDelegate public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { } public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { if let progressHandler { let progress = Progress(totalUnitCount: totalBytesExpectedToWrite) progress.completedUnitCount = totalBytesWritten progressHandler(progress.fractionCompleted) } } } For some reason I get delegate callbacks from URLSessionDelegate and URLSessionTaskDelegate but never from URLSessionDownloadDelegate. I've tried assigning the delegate to the task or the session (or both), but behavior remains the same. Not sure if related but when I try using background session configuration I crash on let (localUrl, response) = try await session.download(for: request) with the error Completion handler blocks are not supported in background sessions. Use a delegate instead. even though I use the async version of the download task, and assigning delegate to the session, it might point to the reason why none of the delegate functions is getting called (maybe?), but I have no clue why Xcode thinks I'm using completion handler.
Posted
by itayAm.
Last updated
.
Post not yet marked as solved
0 Replies
586 Views
I have enabled “StrictConcurrency” warnings in my project that uses SwiftUI. I have a Commands struct. It has a Button, whose action is calling an async method via Task{}. This builds without warnings within Views, but not Commands. There the compiler reports “Main actor-isolated property 'body' cannot be used to satisfy nonisolated protocol requirement”. Looking at SwiftUI: In View, body is declared @MainActor: @ViewBuilder @MainActor var body: Self.Body { get } In Commands, body is not declared @MainActor: @CommandsBuilder var body: Self.Body { get } So the common practice of making a Button action asynchronous: Button { Task { await model.load() } } label:{ Text("Async Button") } will succeed without warnings in Views, but not in Commands. Is this intentional? I've filed FB13212559. Thank you.
Posted
by Bolsinga.
Last updated
.
Post not yet marked as solved
5 Replies
683 Views
In a thread titled “Avoid Dispatch Global Concurrent Queues” [1], Quinn links to a video from WWDC 2015 Session 718, “Building Responsive and Efficient Apps with GCD”. However, this video is not available from the Apple Developer Videos site; only a half dozen or so videos from 2015 are available. This same issue of the missing video came up about five years ago, when Quinn stated that the video had been mistakenly removed but had been restored. Now it’s gone again. :sad_face: Could this video be restored again, or at least its transcript? While I understand that Apple is focused on Swift concurrency, I need to maintain some Objective-C code that uses GCD, and in tracking down some performance issues, I would like to better understand the tradeoffs in the existing code and make improvements where I can. I don’t have the resources to reimplement the code in Swift right now. (More generally, why can't Apple just leave all these videos online indefinitely, for historical purposes at least? Couldn't the ones deemed “old and misleading” just be tagged with a banner like the legacy documentation has?) [1] I like to think of these valuable threads as “Quinn Technical Notes”; I have a page in my Notes app that holds links to the ones I’ve found.
Posted Last updated
.
Post not yet marked as solved
0 Replies
513 Views
Currently, PhotosPickerItem cannot be used from async/await code safely, for example in Tasks etc., because it does not conform to Sendable. The public api has only two properties, both of which are of a Sendable type: UTType and String?. Is this something that's going to be changed so I can mark it as @unchecked Sendable in my code, or is there an actual underlying reason why PhotosPickerItem is not Sendable? PHAsset, PHAssetCollection, PHFetchRequest, PHObject are all sendable, because - similarly to PhotosPickerItem - they contain no actual image data, they are just a preliminary representation of an image in the Photos app.
Posted Last updated
.