Ios 操作状态不是线程安全的

Ios 操作状态不是线程安全的,ios,swift,multithreading,nsoperation,nsoperationqueue,Ios,Swift,Multithreading,Nsoperation,Nsoperationqueue,我将操作子类化,以支持异步操作。 新类名为AsyncOperation,并添加了名为state 这是一个枚举,用于帮助管理操作状态 class AsyncOperation: Operation { // DONE: State enum with keyPath property enum State: String { case Ready, Executing, Finished fileprivate var keyPath: String { return "is" + r

我将
操作
子类化,以支持异步操作。 新类名为
AsyncOperation
,并添加了名为
state
这是一个
枚举
,用于帮助管理操作状态

class AsyncOperation: Operation {
// DONE: State enum with keyPath property
enum State: String {
   case Ready, Executing, Finished

fileprivate var keyPath: String {
  return "is" + rawValue
  }
}

// DONE: state property
var state = State.Ready {
  willSet {
    willChangeValue(forKey: newValue.keyPath)
    willChangeValue(forKey: state.keyPath)
  }
  didSet {
  didChangeValue(forKey: oldValue.keyPath)
  didChangeValue(forKey: state.keyPath)
  }
 }
}




 extension AsyncOperation {
 // DONE: Operation Overrides
 override var isReady: Bool {
 return super.isReady && state == .Ready
 }

 override var isExecuting: Bool {
    return state == .Executing
 }

 override var isFinished: Bool {
   return state == .Finished
 }

 override var isAsynchronous: Bool {
  return true
 }

 override func start() {
  if isCancelled {
  state = .Finished
  return
 }
 main()
 state = .Executing
 }

override func cancel() {
   state = .Finished
 }

}
总的来说,这个子类运行得很好,我对此非常满意。 我经历了一些奇怪的行为。。。 在某些情况下,我会向队列添加操作,如下所示:

//this code happens in mainViewController

//op is an operation that belong to mainViewController and could dispatched to the queue from many places, its init called once in view did load. 
op = SomeAsyncOperation()


if(op.state == .Executing){
  queue.addOperatiom(op)
}

而应用程序崩溃是因为操作以某种方式已经调度到队列,当我用断点检查时,我创建的
状态
属性是
就绪
,原始操作的
isExecuting
字段是
。发生的是我的
状态
属性,操作状态字段未同步。如果我在不同的实现中检查
状态
字段,它确实会进入
执行
完成
如何确保它们始终同步?

您应该使用NSLock来保护对
状态
属性的读写

查看WWDC 2015会议的示例代码

重要的部分是:

/// Private storage for the `state` property that will be KVO observed.
private var _state = State.Initialized

/// A lock to guard reads and writes to the `_state` property
private let stateLock = NSLock()

private var state: State {
    get {
        return stateLock.withCriticalScope {
            _state
        }
    }

    set(newState) {
        /*
            It's important to note that the KVO notifications are NOT called from inside
            the lock. If they were, the app would deadlock, because in the middle of
            calling the `didChangeValueForKey()` method, the observers try to access
            properties like "isReady" or "isFinished". Since those methods also
            acquire the lock, then we'd be stuck waiting on our own lock. It's the
            classic definition of deadlock.
        */
        willChangeValueForKey("state")

        stateLock.withCriticalScope { Void -> Void in
            guard _state != .Finished else {
                return
            }

            assert(_state.canTransitionToState(newState), "Performing invalid state transition.")
            _state = newState
        }

        didChangeValueForKey("state")
    }
}