# \[iOS] Asynchronous Operation

iOS的Operation是synchronous的,  無法做到一些asynchronous的動作如排序下載檔案, 這時候就需要自己寫一個asynchronous的Operation.

**FCAsynchronousOperation**:

(1.) 繼承Operation

(2.) override **isAsynchronous**變數, 設為true

(3.)  override **isReady**,  **isExecuting**, **isFinished** 三個變數

&#x20;      (此例用一個**state**變數結合KVO來實現)

(4.)  override **start**()與**main**() function

(5.) 新增一個finish() function 來定義Asynchronous Operation何時結束

(6.) 繼承**FCAsynchronousOperation**的subclass 需implement main() function

```swift
import UIKit

public class FCAsynchronousOperation: Operation {
    
    @objc private enum State: Int {
        case ready
        case executing
        case finished
    }
    
    /// Concurrent queue for synchronizing access to `state`.
    private let stateQueue = DispatchQueue(label: Bundle.main.bundleIdentifier! + ".operationQueue.state", attributes: .concurrent)
    
    /// Private backing stored property for `state`.
    private var _state: State = .ready
    
    /// The state of the operation
    @objc private dynamic var state: State {
        get { return stateQueue.sync { _state } }
        set { stateQueue.sync(flags: .barrier) { _state = newValue } }
    }
    
    // MARK: - Various `Operation` properties
    open override var isAsynchronous: Bool { return true }
    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 }
    
    // 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 {
            finish()
            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 isExecuting { state = .finished }
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://frost.gitbook.io/iosbook/ios/ios-book/ios-asynchronous-operation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
