yageek
yageek

Reputation: 4464

Passing Data Between Two NSOperations

I watched with a great attention the WWDC 2015 sessions about Advanced NSOperations and I played a little bit with the example code.

The provided abstraction are really great, but there is something I may did not really good understand.

I would like to pass result data between two consequent Operation subclasses without using a MOC.

Imagine I have a APIQueryOperation which has a NSData? property and a second operation ParseJSONOperation consuming this property. How do I provide this NSData? intance to the second operation ?

I tried something like this :

queryOperation = APIQueryOperation(request: registerAPICall)  
parseOperation = ParseJSONOperation(data: queryOperation.responseData)  
parseOperation.addDependency(queryOperation) 

But when I enter in the execute method of the ParseJSONOperation the instance in not the same as the same as in the initialiser.

What did I do wrong ?

Upvotes: 2

Views: 1671

Answers (1)

Daniel Galasko
Daniel Galasko

Reputation: 24247

Your issue is that you are constructing your ParseJSONOperation with a nil value. Since you have two operations that rely on this NSData object I would suggest you write a wrapper object to house this data.

To try and be aligned with the WWDC talk lets call this object the APIResultContext:

class APIResultContext {
    var data: NSData?
}

now we can pass this object into both the APIQueryOperation and the ParseJSONOperation so that we have a valid object that can store the data transferred from the API.

This would make the constructors for the query:

let context = APIResultContext()
APIQueryOperation(request: registerAPICall, context: context)
ParseJSONOperation(context: context)  

Inside your ParseJSONOperation you should be able to access the data assuming the query completes after it sets the data.

Thread Safety

As @CouchDeveloper pointed out, data is not strictly speaking thread safe. For this trivial example since the two operations are dependent we can safely write and read knowing that these accesses wont take place at the same time. However, to round the solution up and make the context thread safe we can add a simple NSLock

class APIResultContext {
    var data: NSData? {
        set {
            lock.lock()
            _data = newValue
            lock.unlock()
        }
        get {
            lock.lock()
            var result =  _data
            lock.unlock()
            return result
        }
    }

    private var _data: NSData?
    private let lock = NSLock()
}

Upvotes: 8

Related Questions