swiftjsonencoder

Can I cancel a JSONEncoder Swift?


I have a JSONEncoder encoding a 20mb file, which takes ages to process. If the data it's processing changes, I'd like to cancel the encoding, and restart the encoding process but I can't think of a way to do this. Any ideas? I could call JSONEncoder.encode again, but now I would have two 30 second processes running, and double the amount of memory and processor overhead. It would be lovely to be able cancel the previous one.

EDIT: Some of you requested to see my encoder. Here's the one which I'd say causes the biggest bottleneck...

func encode(to encoder: Encoder) throws {
        try autoreleasepool {
            var container = encoder.container(keyedBy: CodingKeys.self)
            try container.encode(brush, forKey: .brush)

            if encoder.coderType == CoderType.export {
                let bezierPath = try NSKeyedUnarchiver.unarchivedObject(ofClass: UIBezierPath.self, from: beziersData)
                let jsonData = try UIBezierPathSerialization.data(with: bezierPath, options: UIBezierPathWritingOptions.ignoreDrawingProperties)
                let bezier = try? JSONDecoder().decode(DBBezier.self, from: jsonData)
                try container.encodeIfPresent(bezier, forKey: .beziersData)
            } else {
                try container.encodeIfPresent(beziersData, forKey: .beziersData)
            }
        }
    }

Solution

  • You can use OperationQueue and add your long running task into that operation queue.

    var queue: OperationQueue?
    //Initialisation
    if queue == nil {
        queue = OperationQueue()
        queue?.maxConcurrentOperationCount = 1
    }
    queue?.addOperation {
        //Need to check the isCanceled property of the operation for stopping the ongoing execution in any case.
        self.encodeHugeJSON()
    }
    

    You can also cancel the task whenever you want using the following code:

    //Whenever you want to cancel the task, you can do it like this
    queue?.cancelAllOperations()
    queue = nil
    

    What is an Operation Queue:

    An operation queue invokes its queued Operation objects based on their priority and readiness. After you add an operation to a queue, it remains in the queue until the operation finishes its task. You can’t directly remove an operation from a queue after you add it.

    Reference links: