gpt4 book ai didi

swift - 尝试理解异步操作子类

转载 作者:IT王子 更新时间:2023-10-29 05:13:02 27 4
gpt4 key购买 nike

我正在尝试开始使用 Operation s 在一个副项目中,而不是在我的网络代码中散布基于闭包的回调,以帮助消除嵌套调用。所以我正在阅读有关该主题的一些资料,然后遇到了 this实现:

open class AsynchronousOperation: Operation {

// MARK: - Properties

private let stateQueue = DispatchQueue(label: "asynchronous.operation.state", attributes: .concurrent)

private var rawState = OperationState.ready

private dynamic var state: OperationState {
get {
return stateQueue.sync(execute: {
rawState
})
}
set {
willChangeValue(forKey: "state")
stateQueue.sync(flags: .barrier, execute: {
rawState = newValue
})
didChangeValue(forKey: "state")
}
}

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


// MARK: - NSObject

private dynamic class func keyPathsForValuesAffectingIsReady() -> Set<String> {
return ["state"]
}

private dynamic class func keyPathsForValuesAffectingIsExecuting() -> Set<String> {
return ["state"]
}

private dynamic class func keyPathsForValuesAffectingIsFinished() -> Set<String> {
return ["state"]
}


// MARK: - Foundation.Operation

public final override func start() {
super.start()

if isCancelled {
finish()
return
}

state = .executing
execute()
}


// MARK: - Public

/// Subclasses must implement this to perform their work and they must not call `super`. The default implementation of this function throws an exception.
open func execute() {
fatalError("Subclasses must implement `execute`.")
}

/// Call this function after any work is done or after a call to `cancel()` to move the operation into a completed state.
public final func finish() {
state = .finished
}
}

@objc private enum OperationState: Int {

case ready

case executing

case finished
}

这个Operation有一些实现细节我希望在理解方面有所帮助的子类。

  1. stateQueue 的目的是什么?属性(property)?我看到它被 get 使用和 setstate计算属性,但我找不到任何解释 sync:flags:execute 的文档和 sync:execute他们使用的方法。

  2. NSObject 中三个类方法的用途是什么?返回的部分 ["state"] ?我没有看到它们在任何地方被使用。我发现,在 NSObject , class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String> ,但这似乎无法帮助我理解为什么要声明这些方法。

最佳答案

你说:

  1. What is the purpose of the stateQueue property? I see it being used by get and set of the state computed property, but I can't find any documentation that explains the sync:flags:execute and sync:execute methods that they use.

此代码“同步”对属性的访问以使其线程安全。关于为什么需要这样做,请参阅 the Operation documentation ,其中建议:

Multicore Considerations

... When you subclass NSOperation, you must make sure that any overridden methods remain safe to call from multiple threads. If you implement custom methods in your subclass, such as custom data accessors, you must also make sure those methods are thread-safe. Thus, access to any data variables in the operation must be synchronized to prevent potential data corruption. For more information about synchronization, see Threading Programming Guide.

关于这个并发队列用于同步的确切用途,这被称为“读写器”模式。读写器模式的基本概念是读取可以彼此并发发生(因此 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 子类中读写器的使用更简单,但上面说明了模式。

您还问:

  1. What is the purpose of the three class methods in the NSObject section that return ["state"]? I don't see them being used anywhere. I found, in NSObject, class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String>, but that doesn't seem to help me understand why these methods are declared.

这些只是确保对 state 属性的更改触发属性 isReady isExecuting isFinished 的 KVO 通知的方法。这三个键的 KVO 通知对于异步操作的正确运行至关重要。不管怎样,这个语法在 Key-Value Observing Programming Guide: Registering Dependent Keys 中有概述。

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


顺便说一句,这是您提供的 AsynchronousOperation 类的修订版本,即:

  1. 您不能调用 super.start() 。正如 start documentation 所说(强调):

    If you are implementing a concurrent operation, you must override this method and use it to initiate your operation. Your custom implementation must not call super at any time.

  2. 添加 Swift 4 所需的 @objc

  3. execute 重命名为使用 main ,这是 Operation 子类的约定。

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

  5. 使用 #keyPath 使代码更安全/更健壮。

  6. 使用 dynamic 属性时,您不需要手动进行 KVO 通知。本例不需要手动调用willChangeValuedidChangeValue

  7. 更改 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 }
}
}

关于swift - 尝试理解异步操作子类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43561169/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com