Frank's Book
  • Introduction
  • Privacy Policy
  • Git
    • [Git]Fully delete a git repository created with init
  • iOS
    • iOS Book
      • [iOS] Swift Coding Style
      • [iOS] UnitTest With XCode
      • [iOS] Build a Universal Framework for iOS using Swift
      • [iOS] Memory Management
      • [iOS] GCD And Operation Queue
      • [iOS] MVVM
      • [iOS] CoreData
      • [iOS] KVO & KVC
      • [iOS] Asynchronous Operation
      • [iOS] URLSession
      • [iOS] NSTimer & CADisplayLink
      • [iOS] UITextField & UITestView
      • [iOS] UITableView & UICollectionView
      • [iOS] Codable
      • [iOS] Array的sort, filter, map, reduce 函式
      • [iOS] Class vs Struct
      • [iOS] Reference Type vs Value Type
      • [iOS] Object
      • [iOS] IBDesignable & IBInspectable
  • Jenkins
    • Jenkins & Docker
      • [Docker] Docker Commands
      • [Docker] 1. Setup Jenkins with Docker on Mac
      • [Docker] 2. Jenkins建立Mac子節點
      • [Docker] 3. Mac節點build Xcode project設定
      • [Jenkins] 1. Install Jenkins
      • [Jenkins] 2. Change Default User Of Jenkins
      • [Jenkins] 3. Integration with Git
      • [Jenkins] 4. Integration with XCode
      • [Jenkins] 5. Integration with Unit Test
      • [Jenkins] 6. Uninstall Jenkins
      • [Jenkins] 7. Jenkins Commands
      • [Jenkins] 8. Jenkins Plugins
      • [Jenkins] 9. Problem Solving
  • Flutter
    • Flutter Book
      • [Flutter] Update your Flutter path (Mac OS)
      • [Flutter] Release Command
      • [Flutter] Life Cycles
      • [Flutter] AppLifecycleState
      • [Flutter] Navigator Pop時回傳資料
      • [Flutter] Install appium-flutter-driver
  • Leet Code
    • LeetCode Solutions
      • [LeetCode] 1. Two Sum [Easy]
      • [LeetCode] 2. Add Two Numbers [Medium]
      • [LeetCode] 3. Longest Substring Without Repeating Characters [Medium]
      • [LeetCode] 5. Longest Palindromic Substring [Medium]
      • [LeetCode] 7. Reverse Integer [Easy] [LeetCode]
      • [LeetCode] 8. String to Integer (atoi)
      • [LeetCode] 11. Container With Most Water
      • [LeetCode] 13. Roman to Integer
      • [LeetCode]14. Longest Common Prefix
      • [LeetCode] 15. 3Sum
      • [LeetCode] 17. Letter Combinations of a Phone Number
      • [LeetCode] 19. Remove Nth Node From End of List
      • [LeetCode] 20. Valid Parentheses
      • [LeetCode] 21. Merge Two Sorted Lists
      • [LeetCode] 22. Generate Parentheses
      • [LeetCode] 26. Remove Duplicates from Sorted Array
      • [LeetCode] 28. Implement strStr()
      • [LeetCode] 33. Search in Rotated Sorted Array
      • [LeetCode] 34. Find First and Last Position of Element in Sorted Array
      • [LeetCode]36. Valid Sudoku
      • [LeetCode] 38. Count and Say
      • [LeetCode] 46. Permutations
      • [LeetCode] 48. Rotate Image
      • [LeetCode] 49. Group Anagrams
  • Git
    • Git Commands
      • [LeetCode] 50. Pow(x, n)
  • About Author
    • Frank Chen
Powered by GitBook
On this page
  1. iOS
  2. iOS Book

[iOS] Asynchronous Operation

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

FCAsynchronousOperation:

(1.) 繼承Operation

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

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

(此例用一個state變數結合KVO來實現)

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

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

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

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 }
    }
}
Previous[iOS] KVO & KVCNext[iOS] URLSession

Last updated 6 years ago