But could I suggest a small improvement: in the finish method, inside the perform block, if it called a new method finishOnDispatchQueue to set the state instead of setting it directly, then that method could be overridden by subclasses and allow them to call their own custom completion block and then calling super to change the state and end the operation. This way they can guarantee their completion block is called on the dispatch queue using your nifty code.
But could I suggest a small improvement: in the finish method, inside the perform block, if it called a new method finishOnDispatchQueue to set the state instead of setting it directly, then that method could be overridden by subclasses and allow them to call their own custom completion block and then calling super to change the state and end the operation. This way they can guarantee their completion block is called on the dispatch queue using your nifty code.