2

I am trying to perform an API call on a list of Draft which are queued< (1 call by Draft).

For this I have created a DraftQueue:

actor DraftQueue {
    private var taskQueue = [String: Task<Void, Never>]()

    func cleanQueueElement(uuid: String) {
        taskQueue[uuid]?.cancel()
        taskQueue[uuid] = nil
    }
}

Here is an example of a function supposed to save a Draft online:

private func saveDraft(draft: Draft, mailboxManager: MailboxManager) async {
    await draftQueue.cleanQueueElement(uuid: draft.localUUID)
    await mailboxManager.save(draft: draft)
}

The function saveDraft is called in another function that gets all the Draft that needs to be saved and saves them:

public func syncDraft(mailboxManager: MailboxManager) {
    Task {
        let drafts = await mailboxManager.draftWithPendingAction()
        for draft in drafts {
            Task {
                await self.saveDraft(draft: draft, mailboxManager: mailboxManager)
            }
        }
    }
}

The problem here is that sometimes I get this error in the function cleanQueueElement.

-[NSTaggedPointerString objectForKey:]: unrecognized selector sent to instance 0x8000000000000000

Ambrdctr
  • 21
  • 2
  • try getting rid of the inner `Task` it kind of defeats the purpose of `async await` – lorem ipsum Nov 15 '22 at 12:40
  • I Already tried that – Ambrdctr Nov 15 '22 at 12:52
  • There isn't enough code to reproduce the issue but my guess is that this is a timing issue. That `taskQueue` variable seems suspicious and depending on the setup the outer task in the sync function is also ignoring the concurrent benefits. – lorem ipsum Nov 15 '22 at 12:56
  • What's weird is if the debugger isn't connected, the app doesn't crash. – Ambrdctr Nov 15 '22 at 13:45
  • Have you tried using the diagnostic tools outlined in [Diagnosing memory, thread, and crash issues early](https://developer.apple.com/documentation/xcode/diagnosing-memory-thread-and-crash-issues-early/) (as well as the “Memory Management” settings on the “Diagnostics” tab in your scheme settings)? Also, I’d try setting the “Strict Concurrency Checking” build setting to “Complete”. – Rob Nov 15 '22 at 17:14
  • `taskQueue[uuid] = nil` looks wrong. especially since the value `Task` is not an optional. Are you sure you don't want `taskQueue.removeValue(forKey: uuid)` – Scott Thompson Nov 15 '22 at 18:56
  • 1
    @ScottThompson - `dictionary[key] = nil` is an acceptable way to remove an entry from a dictionary. As the [documentation](https://developer.apple.com/documentation/swift/dictionary/) says, “If you assign `nil` to an existing key, the key and its associated value are removed.” – Rob Nov 16 '22 at 08:04

0 Answers0