Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 试图理解异步操作子类_Swift_Nsoperation - Fatal编程技术网

Swift 试图理解异步操作子类

Swift 试图理解异步操作子类,swift,nsoperation,Swift,Nsoperation,我正试图开始在一个辅助项目中使用操作s,而不是在我的网络代码中到处都是基于闭包的回调,以帮助消除嵌套调用。所以我读了一些关于这个主题的书,我遇到了实现: 开放类异步操作:操作{ //标记:-属性 private let stateQueue=DispatchQueue(标签:“asynchronous.operation.state”,属性:。并发) private var rawState=OperationState.ready 私有动态var状态:OperationState{ 得到{ r

我正试图开始在一个辅助项目中使用
操作
s,而不是在我的网络代码中到处都是基于闭包的回调,以帮助消除嵌套调用。所以我读了一些关于这个主题的书,我遇到了实现:

开放类异步操作:操作{
//标记:-属性
private let stateQueue=DispatchQueue(标签:“asynchronous.operation.state”,属性:。并发)
private var rawState=OperationState.ready
私有动态var状态:OperationState{
得到{
return stateQueue.sync(执行:{
原始状态
})
}
设置{
willChangeValue(forKey:“州”)
stateQueue.sync(标志:。屏障,执行:{
rawState=newValue
})
didChangeValue(forKey:“状态”)
}
}
公共最终覆盖变量已就绪:Bool{
返回状态==.ready&&super.isReady
}
公共最终覆盖变量正在执行:Bool{
返回状态==。正在执行
}
公共最终覆盖变量isFinished:Bool{
返回状态==.finished
}
公共最终覆盖:Bool{
返回真值
}
//标记:-NSObject
私有动态类func KEYPATHSFORVALUESFECTINGISREADY()->Set{
返回[“状态”]
}
私有动态类func keypathsforvaluesafectingisexecuting()->Set{
返回[“状态”]
}
私有动态类func keypathsforvaluesafectingisfinished()->Set{
返回[“状态”]
}
//标记:基础操作
公共最终覆盖函数开始(){
super.start()
如果取消{
完成()
返回
}
状态=.executing
执行()
}
//马克:公众
///子类必须实现此功能才能执行其工作,并且不能调用“super”。此函数的默认实现会引发异常。
open func execute(){
fatalError(“子类必须实现'execute`.”)
}
///在完成任何工作或调用“cancel()”后调用此函数,以将操作移动到完成状态。
公共最终功能完成(){
状态=.finished
}
}
@objc私有枚举操作状态:Int{
案例准备
案件执行
案件审理完毕
}
这个
操作
子类有一些实现细节,我想在理解时得到一些帮助

  • stateQueue
    属性的用途是什么?我看到
    state
    computed属性的
    get
    set
    正在使用它,但是我找不到任何文档来解释它们使用的
    sync:flags:execute
    sync:execute
    方法

  • NSObject
    部分中返回
    [“state”]
    的三个类方法的用途是什么?我看不到它们在任何地方被使用。我在
    NSObject
    中找到了
    类func-keypathsforvaluesafectingvalue(forKey:String)->Set
    ,但这似乎不能帮助我理解为什么要声明这些方法


  • 关于您的第一个问题:stateQueue在向您写入新值时锁定您的操作操作状态,方法是:

        return stateQueue.sync(execute: {
                rawState
        })
    

    由于您的操作是异步的,所以在读取或写入一个状态之前,可以调用另一个状态。就像你想写iExecution,但同时我已经完成了调用。因此,为了避免这种情况,stateQueue锁定要读写的操作状态,直到它完成上一次调用。它像原子弹一样工作。相反,使用调度队列,您可以使用NSLock的扩展来简化执行WWDC 2015中高级NSOperations示例代码中的关键代码,并且您可以实现如下功能:

    private let stateLock = NSLock()
    
    private dynamic var state: OperationState {
        get {
            return stateLock.withCriticalScope{ rawState } 
        }
        set {
            willChangeValue(forKey: "state")
    
            stateLock.withCriticalScope { 
                rawState = newValue
            }
            didChangeValue(forKey: "state")
        }
    }
    
    关于第二个问题:只读属性isReady、isExecuting、isFinished的KVO通知用于管理操作状态。您可以阅读以下内容:为了更好地理解KVO,请将文章张贴到最后

    你说:

  • stateQueue
    属性的用途是什么?我看到它被
    state
    computed属性的get和set使用,但我找不到任何文档来解释它们使用的
    sync:flags:execute
    sync:execute
    方法
  • 此代码“同步”对属性的访问以使其线程安全。关于您为什么需要这样做,请参见,其中建议:

    多核注意事项

    。。。当您将
    NSOperation
    子类化时,必须确保任何重写的方法都可以安全地从多个线程调用。如果在子类中实现自定义方法,例如自定义数据访问器,则还必须确保这些方法是线程安全的。因此,必须同步对操作中任何数据变量的访问,以防止潜在的数据损坏。有关同步的详细信息,请参阅

    关于同步的并发队列的确切使用,这被称为“读写器”模式。读写器模式的这一基本概念是,读取可以相互并发(因此
    sync
    ,没有障碍),但写入不能与该属性的任何其他访问并发(因此
    async
    ,有障碍)

    例如,您可以在如下阵列上实现线程安全读写器:

    class ThreadSafeArray<T> {
        private var values: [T]
        private let queue = DispatchQueue(label: "...", attributes: .concurrent)
        
        init(_ values: [T]) {
            self.values = values
        }
        
        func reader<U>(block: () throws -> U) rethrows -> U {
            return try queue.sync {
                try block()
            }
        }
        
        func writer(block: @escaping (inout [T]) -> Void) {
            queue.async(flags: .barrier) {
                block(&self.values)
            }
        }
        
        // e.g. you might use `reader` and `writer` like the following:
        
        subscript(_ index: Int) -> T {
            get { reader { values[index] } }
            set { writer { $0[index] = newValue } }
        }
        
        func append(_ value: T) {
            writer { $0.append(value) }
        }
        
        func remove(at index: Int) {
            writer { $0.remove(at: index)}
        }
    }
    

    使用中更新的代码段时,应注意此更改可能导致的错误:

  • 更改finish,使其仅在执行时移动到.finished状态
  • 上述情况不利于苹果公司:

    除了在操作取消时简单地退出外,将已取消的操作移动到适当的最终状态也很重要。具体来说,我
    class ThreadSafeArray<T> {
        private var values: [T]
        private let queue = DispatchQueue(label: "...", attributes: .concurrent)
        
        init(_ values: [T]) {
            self.values = values
        }
        
        func reader<U>(block: () throws -> U) rethrows -> U {
            return try queue.sync {
                try block()
            }
        }
        
        func writer(block: @escaping (inout [T]) -> Void) {
            queue.async(flags: .barrier) {
                block(&self.values)
            }
        }
        
        // e.g. you might use `reader` and `writer` like the following:
        
        subscript(_ index: Int) -> T {
            get { reader { values[index] } }
            set { writer { $0[index] = newValue } }
        }
        
        func append(_ value: T) {
            writer { $0.append(value) }
        }
        
        func remove(at index: Int) {
            writer { $0.remove(at: index)}
        }
    }
    
    public class AsynchronousOperation: Operation {
        
        /// State for this operation.
        
        @objc private enum OperationState: Int {
            case ready
            case executing
            case finished
        }
        
        /// Concurrent queue for synchronizing access to `state`.
        
        private let stateQueue = DispatchQueue(label: Bundle.main.bundleIdentifier! + ".rw.state", attributes: .concurrent)
        
        /// Private backing stored property for `state`.
        
        private var _state: OperationState = .ready
        
        /// The state of the operation
        
        @objc private dynamic var state: OperationState {
            get { return stateQueue.sync { _state } }
            set { stateQueue.async(flags: .barrier) { self._state = newValue } }
        }
        
        // MARK: - Various `Operation` properties
        
        open         override var isReady:        Bool { return state == .ready && super.isReady }
        public final override var isExecuting:    Bool { return state == .executing }
        public final override var isFinished:     Bool { return state == .finished }
        public final override var isAsynchronous: Bool { return true }
    
        // KVN for dependent properties
        
        open override class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String> {
            if ["isReady", "isFinished", "isExecuting"].contains(key) {
                return [#keyPath(state)]
            }
            
            return super.keyPathsForValuesAffectingValue(forKey: key)
        }
        
        // Start
        
        public final override func start() {
            if isCancelled {
                state = .finished
                return
            }
            
            state = .executing
            
            main()
        }
        
        /// Subclasses must implement this to perform their work and they must not call `super`. The default implementation of this function throws an exception.
        
        open override func main() {
            fatalError("Subclasses must implement `main`.")
        }
        
        /// Call this function to finish an operation that is currently executing
        
        public final func finish() {
            if !isFinished { state = .finished }
        }
    }