Questions/Possible issues with Advanced Operations sample code

The Advanced NSOperations (https://developer.apple.com/videos/wwdc/2015/?id=226) talk from this year was a real eye opener. I've used NSOperations in my app before but not to the extent as shown in Advanced NSOperations.


I've spent a little time to translate some of the sample code from the Advanced NSOperations for my app and have started using the custom operations and queues to implement CloudKit syncing.


I also took some time to read the Concurrency Programming Guide as well as the docs for NSOperation and NSOperationQueue. As I did I made some notes about things in the docs that didn't seem to match up with the sample code implementation. I'm listing them here just in case they come to anyone else:


In Operation.swift, the isReady method is overwritten to support custom conditions. If the Operation is .Pending, and the super's isReady returns true, then the conditions are evaluated. If the state of the Operation is .Ready, then the operation isReady returns true if the super's isReady returns true. Here is the implementation:


override var ready: Bool {
    switch state {
        case .Pending:
            if super.ready {
                evaluateConditions()
            }
       
            return false
   
        case .Ready:
            return super.ready
   
        default:
            return false
    }
}


In the NSOperation docs however, it states (in regards to overridding the isReady propery):


"In OS X v10.6 and later, if you cancel an operation while it is waiting on the completion of one or more dependent operations, those dependencies are thereafter ignored and the value of this property is updated to reflect that it is now ready to run. This behavior gives an operation queue the chance to flush cancelled operations out of its queue more quickly."


Based on this, it would seem that if the operation is in it's .Cancelled state, isReady should return true, thus allowing giving the queue the chance to flush this operation out of the queue.


Following along the early cancellation thread, in Operation.swift the `-start` method is overridden to look like this:


override final func start() {
    assert(state == .Ready, "This operation must be performed on an operation queue.")
    state = .Executing
   
    for observer in observers {
        observer.operationDidStart(self)
    }
   
    execute()
}


That assert above means that reaching this method in anything other than the .Ready state is a programmer error. But according to the NSOperation docs on -start, this isn't the expected behavior:


"The default implementation of this method updates the execution state of the operation and calls the receiver’s main method. This method also performs several checks to ensure that the operation can actually run. For example, if the receiver was cancelled or is already finished, this method simply returns without calling main. (In OS X v10.5, this method throws an exception if the operation is already finished.) If the operation is currently executing or is not ready to execute, this method throws an

NSInvalidArgumentException
exception. In OS X v10.5, this method catches and ignores any exceptions thrown by your main method automatically. In OS X v10.6 and later, exceptions are allowed to propagate beyond this method. You should never allow exceptions to propagate out of your main method."


Should there be a check here to see if the state is .Cancelled and thus skip calling executing and just go right to .Finished or .Finishing?


That is all I have for now.


Thanks again to the team for this great talk and releasing this sample code to the world.

Replies

The sample will not be updated. WWDC sample code isn't maintained after the conference. Elsewhere in this thread, @Visory points to an open source version of the code that has been updated for Swift 3+.

Thanks Dave,

I suspected that that would be the case. It would not be so bad if Swift were stable, and did not require a complete rewrite every year.

I'll try the linked github, I should have finisehd reading the thread; duh!

Hi Dave,

I have a question regarding ios 10.3 , is the release contains change that affect NSOperation behavior ? Since i can not find the changelog anywhere.

Our opensource SDK use the samplecode and convert it to swift 3, on latest XCode (8.3.1) our testcase ran well on ios 10.2 and below but crashed on 10.3 simulator.


I will create new thread in case this is not a relevan place to discuss.