Concurrency

RSS for tag

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

Posts under Concurrency tag

115 Posts

Post

Replies

Boosts

Views

Activity

How to import large data from Server and save it to Swift Data
Here’s the situation: • You’re downloading a huge list of data from iCloud. • You’re saving it one by one (sequentially) into SwiftData. • You don’t want the SwiftUI view to refresh until all the data is imported. • After all the import is finished, SwiftUI should show the new data. The Problem If you insert into the same ModelContext that SwiftUI’s @Environment(.modelContext) is watching, each insert may cause SwiftUI to start reloading immediately. That will make the UI feel slow, and glitchy, because SwiftUI will keep trying to re-render while you’re still importing. How to achieve this in Swift Data ?
2
0
113
Apr ’25
Xcode UIKit Document App template crashes under Swift 6
I'm trying to switch to UIKit's document lifecycle due to serious bugs with SwiftUI's version. However I'm noticing the template project from Xcode isn't compatible with Swift 6 (I already migrated my app to Swift 6.). To reproduce: File -> New -> Project Select "Document App" under iOS Set "Interface: UIKit" In Build Settings, change Swift Language Version to Swift 6 Run app Tap "Create Document" Observe: crash in _dispatch_assert_queue_fail Does anyone know of a work around other than downgrading to Swift 5?
0
1
82
Apr ’25
Core Data and Swift 6 concurrency: returning an NSManagedObject
We're in the process of migrating our app to the Swift 6 language mode. I have hit a road block that I cannot wrap my head around, and it concerns Core Data and how we work with NSManagedObject instances. Greatly simplied, our Core Data stack looks like this: class CoreDataStack { private let persistentContainer: NSPersistentContainer var viewContext: NSManagedObjectContext { persistentContainer.viewContext } } For accessing the database, we provide Controller classes such as e.g. class PersonController { private let coreDataStack: CoreDataStack func fetchPerson(byName name: String) async throws -> Person? { try await coreDataStack.viewContext.perform { let fetchRequest = NSFetchRequest<Person>() fetchRequest.predicate = NSPredicate(format: "name == %@", name) return try fetchRequest.execute().first } } } Our view controllers use such controllers to fetch objects and populate their UI with it: class MyViewController: UIViewController { private let chatController: PersonController private let ageLabel: UILabel func populateAgeLabel(name: String) { Task { let person = try? await chatController.fetchPerson(byName: name) ageLabel.text = "\(person?.age ?? 0)" } } } This works very well, and there are no concurrency problems since the managed objects are fetched from the view context and accessed only in the main thread. When turning on Swift 6 language mode, however, the compiler complains about the line calling the controller method: Non-sendable result type 'Person?' cannot be sent from nonisolated context in call to instance method 'fetchPerson(byName:)' Ok, fair enough, NSManagedObject is not Sendable. No biggie, just add @MainActor to the controller method, so it can be called from view controllers which are also main actor. However, now the compiler shows the same error at the controller method calling viewContext.perform: Non-sendable result type 'Person?' cannot be sent from nonisolated context in call to instance method 'perform(schedule:_:)' And now I'm stumped. Does this mean NSManageObject instances cannot even be returned from calls to NSManagedObjectContext.perform? Ever? Even though in this case, @MainActor matches the context's actor isolation (since it's the view context)? Of course, in this simple example the controller method could just return the age directly, and more complex scenarios could return Sendable data structures that are instantiated inside the perform closure. But is that really the only legal solution? That would mean a huge refactoring challenge for our app, since we use NSManageObject instances fetched from the view context everywhere. That's what the view context is for, right? tl;dr: is it possible to return NSManagedObject instances fetched from the view context with Swift 6 strict concurrency enabled, and if so how?
0
0
94
Apr ’25
Actors with Combine publishers as properties.
Is it ok for an Actor type to have a Publisher as a property to let others observe changes over time? Or use the @Published property wrapper to achieve this? actor MyActor { var publisher = PassthroughSubject<Int, Never>() var data: Int { didSet { publisher.send(data) } } ... } // Usage var tasks = Set<AnyCancellable>() let actor = MyActor() Task { let publisher = await actor.publisher publisher.sink { print($0) }.store(in: &tasks) } This seems like this should be acceptable. I would expect a Publisher to be thread safe, and as long as the Output is a value type things should be fine. I have been getting random EXC_BAD_ACCESS errors when using this approach. But turning on the address sanitizer causes these crashes to go away. I know that isn't very specific but I wanted to start by seeing if this type of pattern is ok to do.
1
6
2.6k
Apr ’25
Accessing an actor's isolated state from within a SwiftUI view
I'm trying to understand a design pattern for accessing the isolated state held in an actor type from within a SwiftUI view. Take this naive code: actor Model: ObservableObject { @Published var num: Int = 0 func updateNumber(_ newNum: Int) { self.num = newNum } } struct ContentView: View { @StateObject var model = Model() var body: some View { Text("\(model.num)") // <-- Compiler error: Actor-isolated property 'num' can not be referenced from the main actor Button("Update number") { Task.detached() { await model.updateNumber(1) } } } } Understandably I get the compiler error Actor-isolated property 'num' can not be referenced from the main actor when I try and access the isolated value. Yet I can't understand how to display this data in a view. I wonder if I need a ViewModel that observes the actor, and updates itself on the main thread, but get compile time error Actor-isolated property '$num' can not be referenced from a non-isolated context. class ViewModel: ObservableObject { let model: Model @Published var num: Int let cancellable: AnyCancellable init() { let model = Model() self.model = model self.num = 0 self.cancellable = model.$num // <-- compile time error `Actor-isolated property '$num' can not be referenced from a non-isolated context` .receive(on: DispatchQueue.main) .sink { self.num = $0 } } } Secondly, imagine if this code did compile, then I would get another error when clicking the button that the interface is not being updated on the main thread...again I'm not sure how to effect this from within the actor?
3
2
9.7k
Apr ’25
NSFileCoordinator Swift Concurrency
I'm working on implementing file moving with NSFileCoordinator. I'm using the slightly newer asynchronous API with the NSFileAccessIntents. My question is, how do I go about notifying the coordinator about the item move? Should I simply create a new instance in the asynchronous block? Or does it need to be the same coordinator instance? let writeQueue = OperationQueue() public func saveAndMove(data: String, to newURL: URL) { let oldURL = presentedItemURL! let sourceIntent = NSFileAccessIntent.writingIntent(with: oldURL, options: .forMoving) let destinationIntent = NSFileAccessIntent.writingIntent(with: newURL, options: .forReplacing) let coordinator = NSFileCoordinator() coordinator.coordinate(with: [sourceIntent, destinationIntent], queue: writeQueue) { error in if let error { return } do { // ERROR: Can't access NSFileCoordinator because it is not Sendable (Swift 6) coordinator.item(at: oldURL, willMoveTo: newURL) try FileManager.default.moveItem(at: oldURL, to: newURL) coordinator.item(at: oldURL, didMoveTo: newURL) } catch { print("Failed to move to \(newURL)") } } }
0
0
100
Apr ’25
Metal and Swift Concurrency
Hi, Introducing Swift Concurrency to my Metal app has been a bit challenging as Swift Concurrency is limited by the cooperative thread pool. GPU work is obviously not CPU bound and can block forward moving progress, especially when using waitUntilCompleted on the command buffer. For concurrent render work this has the potential of under utilizing the CPU and even creating dead locks. My question is, what is the Metal's teams general recommendation when it comes to concurrency? It seems to me that Dispatch or OperationQueues are still the preferred way for Metal bound tasks in order to gain maximum performance? To integrate with Swift Concurrency my idea is to use continuations that kick off render jobs via Dispatch or Queues? Would this be the best solution to bridge async tasks with Metal work? Thanks!
5
0
1.1k
Apr ’25
DataScannerViewController does't recognize currency less 1.00
Hi, DataScannerViewController does't recognize currencies less than 1.00 (e.g. 0.59 USD, 0.99 EUR, etc.). Why? How to solve the problem? This feature is not described in Apple documentation, is there a solution? This is my code: func makeUIViewController(context: Context) -&gt; DataScannerViewController { let dataScanner = DataScannerViewController(recognizedDataTypes: [ .text(textContentType: .currency)]) return dataScanner }
4
0
149
Apr ’25
Crash with Progress type, Swift 6, iOS 18
We are getting a crash _dispatch_assert_queue_fail when the cancellationHandler on NSProgress is called. We do not see this with iOS 17.x, only on iOS 18. We are building in Swift 6 language mode and do not have any compiler warnings. We have a type whose init looks something like this: init( request: URLRequest, destinationURL: URL, session: URLSession ) { progress = Progress() progress.kind = .file progress.fileOperationKind = .downloading progress.fileURL = destinationURL progress.pausingHandler = { [weak self] in self?.setIsPaused(true) } progress.resumingHandler = { [weak self] in self?.setIsPaused(false) } progress.cancellationHandler = { [weak self] in self?.cancel() } When the progress is cancelled, and the cancellation handler is invoked. We get the crash. The crash is not reproducible 100% of the time, but it happens significantly often. Especially after cleaning and rebuilding and running our tests. * thread #4, queue = 'com.apple.root.default-qos', stop reason = EXC_BREAKPOINT (code=1, subcode=0x18017b0e8) * frame #0: 0x000000018017b0e8 libdispatch.dylib`_dispatch_assert_queue_fail + 116 frame #1: 0x000000018017b074 libdispatch.dylib`dispatch_assert_queue + 188 frame #2: 0x00000002444c63e0 libswift_Concurrency.dylib`swift_task_isCurrentExecutorImpl(swift::SerialExecutorRef) + 284 frame #3: 0x000000010b80bd84 MyTests`closure #3 in MyController.init() at MyController.swift:0 frame #4: 0x000000010b80bb04 MyTests`thunk for @escaping @callee_guaranteed @Sendable () -&gt; () at &lt;compiler-generated&gt;:0 frame #5: 0x00000001810276b0 Foundation`__20-[NSProgress cancel]_block_invoke_3 + 28 frame #6: 0x00000001801774ec libdispatch.dylib`_dispatch_call_block_and_release + 24 frame #7: 0x0000000180178de0 libdispatch.dylib`_dispatch_client_callout + 16 frame #8: 0x000000018018b7dc libdispatch.dylib`_dispatch_root_queue_drain + 1072 frame #9: 0x000000018018bf60 libdispatch.dylib`_dispatch_worker_thread2 + 232 frame #10: 0x00000001012a77d8 libsystem_pthread.dylib`_pthread_wqthread + 224 Any thoughts on why this is crashing and what we can do to work-around it? I have not been able to extract our code into a simple reproducible case yet. And I mostly see it when running our code in a testing environment (XCTest). Although I have been able to reproduce it running an app a few times, it's just less common.
24
7
2.7k
Apr ’25
Warning: Reference to captured var 'hashBag' in concurrently-executing code
I get many warnings like this when I build an old project. I asked AI chatbot which gave me several solutions, the recommended one is: var hashBag = [String: Int]() func updateHashBag() async { var tempHashBag = hashBag // make copy await withTaskGroup(of: Void.self) { group in group.addTask { tempHashBag["key1"] = 1 } group.addTask { tempHashBag["key2"] = 2 } } hashBag = tempHashBag // copy back? } My understanding is that in the task group, the concurrency engine ensures synchronized modifications on the temp copy in multiple tasks. I should not worry about this. My question is about performance. What if I want to put a lot of data into the bag? Does the compiler do some kind of magics to optimize low level memory allocations? For example, the temp copy actually is not a real copy, it is a special reference to the original hash bag; it is only grammar glue that I am modifying the copy.
4
0
157
Apr ’25
Crash when Mutating Array of Tuples with String Property from Multiple Threads
Hi Apple Developer Community, I'm facing a crash when updating an array of tuples from both a background thread and the main thread simultaneously. Here's a simplified version of the code in a macOS app using AppKit: class ViewController: NSViewController { var mainthreadButton = NSButton(title: "test", target: self, action: nil) var numbers = Array(repeating: (dim: Int, key: String)(0, "default"), count: 1000) override func viewDidLoad() { super.viewDidLoad() view.addSubview(mainthreadButton) mainthreadButton.translatesAutoresizingMaskIntoConstraints = false mainthreadButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true mainthreadButton.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true mainthreadButton.widthAnchor.constraint(equalToConstant: 100).isActive = true mainthreadButton.heightAnchor.constraint(equalToConstant: 100).isActive = true mainthreadButton.target = self mainthreadButton.action = #selector(arraytest(_:)) } @objc func arraytest(_ sender: NSButton) { print("array update started") // Background update DispatchQueue.global().async { for i in 0..&lt;1000 { self.numbers[i].dim = i } } // Main thread update var sum = 0 for i in 0..&lt;1000 { numbers[i].dim = i + 1 sum += numbers[i].dim print("test \(sum)") } mainthreadButton.title = "test = \(sum)" } } This results in a crash with the following message: malloc: double free for ptr 0x136040c00 malloc: *** set a breakpoint in malloc_error_break to debug What's interesting: This crash only happens when the tuple contains a String ((dim: Int, key: String)) If I change the tuple type to use two Int values ((dim: Int, key: Int)), the crash does not occur My Questions: Why does mutating an array of tuples containing a String crash when accessed from multiple threads? Why is the crash avoided when the tuple contains only primitive types like Int? Is there an underlying memory management issue with value types containing reference types like String? Any explanation about this behavior and best practices for thread-safe mutation of such arrays would be much appreciated. Thanks in advance!
1
0
128
Apr ’25
Working with Input/Output stream with Swift 6 and concurrency framework
Hello, I am developing an application which is communicating with external device using BLE and L2CAP. I wonder what are the best practices of using Input & Output streams that are established with L2CAP connection when working with Swift 6 concurrency model. I've been trying to find some examples and hints for some time now but unfortunately there isn't much available. One useful thread I've found is: https://developer.apple.com/forums/thread/756281 but it does not offer much insight into using eg. actor model with streams. I wonder if something has changed in this regards? Also, are there any plans to migrate eg. CoreBluetooth stack to new swift 6 concurrency ?
2
0
116
Apr ’25
Return the results of a Spotlight query synchronously from a Swift function
How can I return the results of a Spotlight query synchronously from a Swift function? I want to return a [String] that contains the items that match the query, one item per array element. I specifically want to find all data for Spotlight items in the /Applications folder that have a kMDItemAppStoreAdamID (if there is a better predicate than kMDItemAppStoreAdamID > 0, please let me know). The following should be the correct query: let query = NSMetadataQuery() query.predicate = NSPredicate(format: "kMDItemAppStoreAdamID > 0") query.searchScopes = ["/Applications"] I would like to do this for code that can run on macOS 10.13+, which precludes using Swift Concurrency. My project already uses the latest PromiseKit, so I assume that the solution should use that. A bonus solution using Swift Concurrency wouldn't hurt as I will probably switch over sometime in the future, but won't be able to switch soon. I have written code that can retrieve the Spotlight data as the [String], but I don't know how to return it synchronously from a function; whatever I tried, the query hangs, presumably because I've called various run loop functions at the wrong places. In case it matters, the app is a macOS command-line app using Swift 5.7 & Swift Argument Parser 1.5.0. The Spotlight data will be output only as text to stdout & stderr, not to any Apple UI elements.
1
0
104
Apr ’25
Help Understanding Concurrency Error with Protocol Listener and Actor
Hi all, I'm running into a Swift Concurrency issue and would appreciate some help understanding what's going on. I have a protocol and an actor set up like this: protocol PersistenceListener: AnyObject { func persistenceDidUpdate(key: String, newValue: Any?) } actor Persistence { func addListener(_ listener: PersistenceListener) { listeners.add(listener) } /// Removes a listener. func removeListener(_ listener: PersistenceListener) { listeners.remove(listener) } // MARK: - Private Properties private var listeners = NSHashTable<AnyObject>.weakObjects() // MARK: - Private Methods /// Notifies all registered listeners on the main actor. private func notifyListeners(key: String, value: Any?) async { let currentListeners = listeners.allObjects.compactMap { $0 as? PersistenceListener } for listener in currentListeners { await MainActor.run { listener.persistenceDidUpdate(key: key, newValue: value) } } } } When I compile this code, I get a concurrency error: "Sending 'listener' risks causing data races"
4
0
122
Apr ’25
Swift game sometimes runs on efficiency cores then snaps back to performance cores
I've been working on Swift game which is not yet launched or available for preview. The game works in such a way that it has idle CPU while the user is thinking and sustained max CPU and GPU on as many cores as possible when he makes a move. Rarely, due to OS activity or something else outside of my control (for example when dropping the OS curtain even if for just a bit then remove it), the game or some of its threads are moved to efficiency cores which results in major stuttering which persists precisely until the game is idle again at which point the game is moved back on performance cores - but if the player keeps making moves the stuttering simply won't go away and so I guess compuptation is locked onto efficiency cores. The issue does not reproduce on MacCatalyst on Intel. How do I tell Swift to avoid efficiency cores? BTW Swift and SceneKIT have AMAZING performance especially when compared to others.
0
0
114
Mar ’25
Cast Any to Sendable
I'm continuing with the migration towards Swift 6. Within one of our libraries, I want to check whether a parameter object: Any? confirms to Sendable. I tried the most obvious one: if let sendable = object as? Sendable { } But that results into the compiler error "Marker protocol 'Sendable' cannot be used in a conditional cast". Is there an other way to do this?
5
0
1.5k
Mar ’25
RxSwift Driver got fatal error in Swift Testing because it is not called form main thread.
Hi, I'm trying the new Swift Testing instead of XCTest for my new project. I am using RxSwift+UIKit. And when I am trying to test my ViewModel that has a Driver in it, it crashes due to the driver is not being called form main thread. Thread 5: Fatal error: `drive*` family of methods can be only called from `MainThread`. Here is the test code: struct PlayerViewModelTest { @Test func testInit_shouldPopulateTable_withEmpty() async throws { // Arrange let disposeBag = DisposeBag() var expectedSongTableCellViewData: [SongTableCellViewData]? // Act let sut = PlayerViewModel(provideAllSongs: { return .just(mockSongList) }, provideSongByArtist: { _ in return .just(mockSongList) }, disposeBag: disposeBag) sut.populateTable .drive(onNext: { expectedSongTableCellViewData = $0 }) .disposed(by: disposeBag) // Assert #expect(expectedSongTableCellViewData != nil, "Should emit something so it should not be nil") #expect(expectedSongTableCellViewData!.isEmpty, "Should emit empty array") } } This never happen in XCTest. So I assume Swift Testing is not being run in the main thread? How do I fix this? Thanks
1
0
122
Mar ’25
SwiftData and async functions
Hello, I recently published an app that uses Swift Data as its primary data storage. The app uses concurrency, background threads, async await, and BLE communication. Sadly, I see my app incurs many fringe crashes, involving EXC_BAD_ACCESS, KERN_INVALID_ADDRESS, EXC_BREAKPOINT, etc. I followed these guidelines: One ModelContainer that is stored as a global variable and used throughout. ModelContexts are created separately for each task, changes are saved manually, and models are not passed around. Threads with different ModelContexts might manipulate and/or read the same data simultaneously. I was under the impression this meets the usage requirements. I suspect perhaps the issue lies in my usage of contexts in a single await function, that might be paused and resumed on a different thread (although same execution path). Is that the case? If so, how should SwiftData be used in async scopes? Is there anything else particularly wrong in my approach?
4
0
1.2k
Mar ’25
autoreleasepool with async await
I ran into a problem, I have a recursive function in which Data type objects are temporarily created, because of this, the memory expands until the entire recursion ends. It would just be fixed using autoreleasepool, but it can't be used with async await, and I really don't want to rewrite the code for callbacks. Is there any option to use autoreleasepool with async await functions? (I Googled one option, that the Task already contains its own autoreleasepool, and if you do something like that, it should work, but it doesn't, the memory is still growing) func autoreleasepool&lt;Result&gt;(_ perform: @escaping () async throws -&gt; Result) async throws -&gt; Result { try await Task { try await perform() }.value }
2
0
162
Mar ’25
CoreBluetooth and Swift strict concurrency checking
As of iOS 18.3 SDK, Core Bluetooth is still mostly an Objective-C framework: key objects like CBPeripheral inherit from NSObjectProtocol and does not conform to Sendable. CBCentralManager has a convenience initializer that allows the caller to provide a dispatch_queue for delegate callbacks. I want my Swift package that implements Core Bluetooth to conform to Swift 6 strict concurrency checking. It is unsafe to dispatch the delegate events onto my own actor, as the passed in objects are presumably not thread-safe. What is the recommended concurrency safe way to implement Core Bluetooth in Swift 6 with strict concurrency checking enabled?
0
0
123
Mar ’25