I have two NSOperation
that are responsible for Downloading, and Parsing. After the downloading operation is successful and I receive some NSData
I want to then set that data as the data to be used by the parsing operation:
init(context: NSManagedObjectContext, completionHandler: Void -> Void) {
downloadOperation = DownloadActivitiesOperation() { data in
self.parseOperation.data = data
}
parseOperation = ParseActivitiesOperation(context: context)
let finishOperation = NSBlockOperation(block: completionHandler)
parseOperation.addDependency(downloadOperation)
finishOperation.addDependency(parseOperation)
super.init(operations: [downloadOperation, parseOperation, finishOperation])
name = "Get Activities"
}
This however doesn't work as I'm attempting to use self
inside of my download completion block before calling super.init
.
My question is what would be the best approach when attempting to pass the result of one operation to the next one in the chain?
Each instance of NSOperation
contains array of dependencies. Operations are not removed from this array after finishing. You can use those objects to access the data:
class DownloadActivitiesOperation: NSOperation {
var data: NSData?
...
// set self.data when it has downloaded
}
class ParseActivitiesOperation: NSOperation {
func main() {
if let downloadOp = self.dependencies.last as? DownloadActivitiesOperation {
let dataToParse = downloadOp.data
...
}
}
}
And so on.
It looks like you are using some kind of implementation of GroupOperation
from the WWDC2015 talk on Advanced NSOperations. In the sample code from the talk they use a cache file to pass data between the downloader and the parser.
Following snippet from the GetEarthquakesOperation
class:
let cachesFolder = try! NSFileManager.defaultManager().URLForDirectory(.CachesDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: true)
let cacheFile = cachesFolder.URLByAppendingPathComponent("earthquakes.json")
/*
This operation is made of three child operations:
1. The operation to download the JSON feed
2. The operation to parse the JSON feed and insert the elements into the Core Data store
3. The operation to invoke the completion handler
*/
downloadOperation = DownloadEarthquakesOperation(cacheFile: cacheFile)
parseOperation = ParseEarthquakesOperation(cacheFile: cacheFile, context: context)
My current solution in one of my projects is to wrap the results in a class and pass it to both operations:
class OperationResultWrapper<T> {
var result: T?
}
let wrapper = OperationResultWrapper<NSData>()
downloadOperation = DownloadEarthquakesOperation(resultWrapper: wrapper)
parseOperation = ParseEarthquakesOperation(dataWrapper: wrapper, context: context)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With