栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

试图理解异步操作子类

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

试图理解异步操作子类

你说:

1.

stateQueue
物业的目的是什么?我看到
state
计算属性的get和set正在使用它,但是找不到任何解释它们使用的
sync:flags:execute
sync:execute
方法的文档。


此代码“同步”对属性的访问以使其线程安全。至于为什么你需要做的是,看到的

Operation
文件,其中建议:

多核注意事项

…当您继承子类时

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)}    }}

显然,在此

Operation
子类中使用reader-writer 更加简单,但是上面说明了这种模式。

您还问:

2.

NSObject
返回部分中的三个类方法的目的是什么
["state"]
?我看不到它们在任何地方都被使用过。我在中找到了
NSObject
classfunc keyPathsForValuesAffectingValue(forKey key: String) ->Set<String>
但似乎并不能帮助我理解为什么要声明这些方法。

这些是确保变更的只是方法

state
的属性的属性触发志愿通知
isReady
isExecuting
以及
isFinished
。这三个键的KVO通知对于异步操作的正确运行至关重要。无论如何,《键值观察编程指南:注册从属键》中概述了该语法。

keyPathsForValuesAffectingValue
您找到的方法是相关的。您可以使用该方法注册依赖键,也可以使用原始代码段中所示的各个方法。


顺便说一句,这是

AsynchronousOperation
您提供的课程的修订版,即:

  1. 您不得致电
    super.start()
    。如
    start
    文档所述(强调):

如果要实现并发操作,则必须重写此方法并使用它来启动操作。 您的自定义实现不得

super
在任何时候调用。

  1. @objc
    在Swift 4中添加必需项。

  2. 重命名

    execute
    为use
    main
    ,这是
    Operation
    子类的约定。

  3. 声明

    isReady
    final
    属性是不合适的。任何子类都应有权进一步完善其
    isReady
    逻辑(尽管我们承认很少这样做)。

  4. 使用

    #keyPath
    ,使代码更安全/健壮。

  5. 使用

    dynamic
    属性时,您无需手动进行KVO通知。在此示例中,不需要手动调用
    willChangevalue
    didChangevalue

  6. 进行更改

    finish
    ,使其仅在
    .finished
    尚未完成时才进入状态。

从而:

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 }    }}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/370765.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号