GCD 노트

7260 단어
다음은 GCD를 공부하는 작은 노트입니다. 먼저 적어 두었다가 잊어버리면 다시 돌이켜 볼 수 있습니다.

Dispatch Async


다른 대기열에서는 시간이 많이 소요되는 작업을 비동기적으로 수행한 후 마스터 스레드 코드로 돌아갑니다. 예:
// background global queue and run the work in the closure asynchronously
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
  guard let self = self else {
    return
  }
  // do some hard thing
  let image = network.fetchImage()
 
  // update ui in main thread
  DispatchQueue.main.async { [weak self] in
    // update main thread imageView image when image downloaded
    self?.imageView.image = image
  }
}

읽기 및 쓰기 문제 처리


다음은 기능 코드 추가 및 읽기에 대한 단일 예제 클래스 처리 예입니다.
final class PhotoManager {
    
    /*
     GCD provides an elegant solution of creating a read/write lock
     using dispatch barriers. Dispatch barriers are a group of functions
     acting as a serial-style bottleneck when working with concurrent queues
     
     When you submit a DispatchWorkItem to a dispatch queue you can set flags
     to indicate that it should be the only item executed on the specified
     queue for that particular time. This means that all items submitted to
     the queue prior to the dispatch barrier must complete before the
     DispatchWorkItem will execute.
     
     When the DispatchWorkItem‘s turn arrives, the barrier executes it and
     ensures that the queue does not execute any other tasks during that time.
     Once finished, the queue returns to its default implementation.
     */
    
    private init() {}
    static let shared = PhotoManager()
    
    // create a concurrent queue
    private let concurrentQueue = DispatchQueue(label: "com.zhu.xxxxxxxxxxx", attributes: DispatchQueue.Attributes.concurrent)
   
    private var unsafePhotos: [Photo] = []
    
    // read photos
    var photos: [Photo] {
        var photosCopy: [Photo] = []
        // need photo value, so use sync
        concurrentQueue.sync {
            photosCopy = self.unsafePhotos
        }
        // return the value
        return photosCopy
    }
    
    // add photos
    func addPhoto(_ photo: Photo) {
        // add a barrier to write, act like serial queue now
        concurrentQueue.async(flags: .barrier) { [weak self] in
            guard let self = self else { return }
            
            // add photo
            self.unsafePhotos.append(photo)
            
            // notify main thread
            DispatchQueue.main.async { [weak self] in
                self?.postContentAddedNotification()
            }
        }
    }
}

Dispatch Groups


다음은 여러 장의 사진 인터넷 다운로드의 예이다
wait() DispatchGroup manages dispatch groups. You’ll first look at its wait method. This blocks your current thread until all the group's enqueued tasks finish 코드 예:
    func downloadPhotos(withCompletion completion: BatchPhotoDownloadingCompletionClosure?) {
        // async a global queue
        DispatchQueue.global(qos: .userInitiated).async {
            var storedError: NSError?
            
            // a group object
            let downloadGroup = DispatchGroup()
            
            for address in [PhotoURLString.overlyAttachedGirlfriend,
                            PhotoURLString.successKid,
                            PhotoURLString.lotsOfFaces] {
                               
                                // a task start
                                downloadGroup.enter()
                                
                                let url = URL(string: address)
                                let photo = DownloadPhoto(url: url!) { _, error in
                                    if error != nil {
                                        storedError = error
                                    }
                                    // complete that task
                                    downloadGroup.leave()
                                }
                                PhotoManager.shared.addPhoto(photo)
            }
            // will block current thread (use DispatchQueue.global(qos: .userInitiated).async not affect main thread)
            downloadGroup.wait()

            // mission done
            DispatchQueue.main.async {
                completion?(storedError)
            }
        }
    }


그러나 wait () 를 사용하면 현재 라인을 막을 수 있기 때문에 더 좋은 방법은 notify 코드의 예를 사용하는 것입니다.
    func downloadPhotos(withCompletion completion: BatchPhotoDownloadingCompletionClosure?) {
        var storedError: NSError?
        
        // create a dispathc group
        let downloadGroup = DispatchGroup()
        for address in [PhotoURLString.overlyAttachedGirlfriend,
                        PhotoURLString.successKid,
                        PhotoURLString.lotsOfFaces] {
                            let url = URL(string: address)
                            // start a task
                            downloadGroup.enter()
                            let photo = DownloadPhoto(url: url!) { _, error in
                                if error != nil {
                                    storedError = error
                                }
                                // a task done
                                downloadGroup.leave()
                            }
                            PhotoManager.shared.addPhoto(photo)
        }
        
        // use notify work like asynchronous and not block current thread
        downloadGroup.notify(queue: DispatchQueue.main) {
            completion?(storedError)
        }
    }

작업 취소


DispatchWorkItem을 사용하여 아날로그 작업을 취소합니다. 코드 예제에서는 일부 이미지 다운로드 취소 코드 예제를 보여 줍니다.
    func downloadPhotos(withCompletion completion: BatchPhotoDownloadingCompletionClosure?) {
        var storedError: NSError?
        
        // create a dispathc group
        let downloadGroup = DispatchGroup()
        var addresses = PhotoURLString.items
        
        // hold dispatch blocks
        var blocks: [DispatchWorkItem] = []
        
        for index in 0..

참조:
https://www.raywenderlich.com/5370-grand-central-dispatch-tutorial-for-swift-4-part-1-2 https://developer.apple.com/library/archive/documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html https://developer.apple.com/videos/play/wwdc2016/720/

좋은 웹페이지 즐겨찾기