[swift] Swift 3, Swift 4 이상에서 dispatch_sync, dispatch_async, dispatch_after 등을 어떻게합니까?

Swift 2.x (또는 1.x) 프로젝트에는 다음과 같은 코드가 많이 있습니다.

// Move to a background thread to do some long running work
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    let image = self.loadOrGenerateAnImage()
    // Bounce back to the main thread to update the UI
    dispatch_async(dispatch_get_main_queue()) {
        self.imageView.image = image
    }
}

또는 다음과 같은 것들이 실행을 지연시킵니다.

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.5 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
    print("test")
}

또는 Grand Central Dispatch API의 다른 모든 용도 중 하나 …

Swift 3 용 Xcode 8 (베타)에서 프로젝트를 열었으므로 모든 종류의 오류가 발생합니다. 그들 중 일부는 내 코드를 수정하도록 제안하지만 모든 수정 사항이 작동 코드를 생성하는 것은 아닙니다. 이것에 대해 어떻게해야합니까?



답변

Swift는 처음부터 ObjC 및 C를 더욱 신속하게 만드는 기능을 제공하여 각 버전에 더 많은 기능을 추가했습니다. 이제 Swift 3에서 새로운 “멤버로 가져 오기” 기능을 사용하면 특정 스타일의 C API (클래스처럼 작동하는 데이터 유형과 함께 사용할 수있는 전역 함수)가있는 프레임 워크를 사용할 수 있습니다. 스위프트 네이티브 API와 비슷하게 작동합니다. 데이터 유형은 Swift 클래스로 가져오고 관련 전역 함수는 해당 클래스의 메소드 및 특성으로 가져 오며 상수 세트와 같은 일부 관련 항목은 적절한 경우 하위 유형이 될 수 있습니다.

Xcode 8 / Swift 3 베타에서 Apple은 Dispatch 프레임 워크를 훨씬 더 Swifty로 만들기 위해이 기능을 (다른 몇 가지와 함께) 적용했습니다. (그리고 Core Graphics 도 마찬가지입니다.) Swift 오픈 소스 노력을 겪고 있다면 이것은 뉴스 가 아니지만 Xcode의 첫 번째 사례 입니다.

프로젝트를 Swift 3으로 옮기는 첫 번째 단계 는 Xcode 8에서 프로젝트를 열고 메뉴에서 편집> 변환> 현재 Swift 구문으로 … 를 선택하는 것입니다. 이름이 바뀐 모든 API 및 기타 변경 사항에 필요한 모든 변경 사항이 검토 및 승인과 함께 한 번에 적용됩니다. (종종 한 줄의 코드가 한 번에 이러한 변경 중 둘 이상에 영향을 받으므로 오류 수정에 개별적으로 응답하면 모든 것이 올바르게 처리되지 않을 수 있습니다.)

결과적으로 작업을 배경으로 되 돌리는 일반적인 패턴은 다음과 같습니다.

// Move to a background thread to do some long running work
DispatchQueue.global(qos: .userInitiated).async {
    let image = self.loadOrGenerateAnImage()
    // Bounce back to the main thread to update the UI
    DispatchQueue.main.async {
        self.imageView.image = image
    }
}

.userInitiated이전 DISPATCH_QUEUE_PRIORITY상수 중 하나 대신 사용 하고 있습니다. 서비스 품질 (QoS) 지정자는 OS X 10.10 / iOS 8.0에 도입되어 시스템이 작업의 우선 순위를 지정하고 이전 우선 순위 지정자를 더 이상 사용하지 않는 명확한 방법을 제공합니다. 자세한 내용 은 백그라운드 작업 및 에너지 효율성 에 관한 Apple의 문서 를 참조하십시오.

당신이 작업을 구성하기 위해 자신의 대기열을 유지하는 경우 (통지 그런데, 방법은 하나가 지금과 같은 얻을 수 DispatchQueueAttributes입니다 OptionSet당신이 옵션을 결합 컬렉션 스타일의 리터럴을 사용할 수 있도록)

class Foo {
    let queue = DispatchQueue(label: "com.example.my-serial-queue",
                           attributes: [.serial, .qosUtility])
    func doStuff() {
        queue.async {
            print("Hello World")
        }
    }
}

dispatch_after나중에 일하는 데 사용 하십니까? 그것은 대기열에있는 방법이기도하며 DispatchTime, 다양한 숫자 유형에 대한 연산자가 있으므로 전체 또는 분수 초를 추가 할 수 있습니다.

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { // in half a second...
    print("Are we there yet?")
}

Xcode 8에서 인터페이스를 열어서 새로운 Dispatch API를 둘러 볼 수 있습니다 .Open을 사용하여 Dispatch 모듈을 찾거나 DispatchQueueSwift 프로젝트 / 놀이터에 기호 (예 :)를 입력하고 명령을 클릭 한 다음 주변을 둘러보세요 거기에서 모듈. ( Apple의 새롭고 새로운 API 참조 웹 사이트 및 Xcode 문서 뷰어에서 Swift Dispatch API를 찾을 수 있지만 C 버전의 문서 내용이 아직 옮겨지지 않은 것 같습니다.)

자세한 내용은 마이그레이션 안내서 를 참조하십시오 .


답변

Xcode 8 베타 4에서는 작동하지 않습니다 …

사용하다:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    print("Are we there yet?")
}

비동기 두 가지 방법으로 :

DispatchQueue.main.async {
    print("Async1")
}

DispatchQueue.main.async( execute: {
    print("Async2")
})


답변

이것은 다음에 Swift 4대한 좋은 예입니다 async.

DispatchQueue.global(qos: .background).async {
    // Background Thread
    DispatchQueue.main.async {
        // Run UI Updates or call completion block
    }
}


답변

Xcode 8에서 사용 :

DispatchQueue.global(qos: .userInitiated).async { }


답변

스위프트 5.2, 4 이상

메인 및 백그라운드 큐

let main = DispatchQueue.main
let background = DispatchQueue.global()
let helper = DispatchQueue(label: "another_thread") 

비동기 및 동기화 스레드 작업 !

 background.async { //async tasks here }
 background.sync { //sync tasks here } 

비동기 스레드는 기본 스레드와 함께 작동합니다.

동기화 스레드는 실행 중에 메인 스레드를 차단합니다.


답변

Swift 4.1과 5. 우리는 코드의 여러 곳에서 대기열을 사용합니다. 그래서 모든 대기열이있는 Threads 클래스를 만들었습니다. Threads 클래스를 사용하지 않으려는 경우 클래스 메소드에서 원하는 큐 코드를 복사 할 수 있습니다.

class Threads {

  static let concurrentQueue = DispatchQueue(label: "AppNameConcurrentQueue", attributes: .concurrent)
  static let serialQueue = DispatchQueue(label: "AppNameSerialQueue")

  // Main Queue
  class func performTaskInMainQueue(task: @escaping ()->()) {
    DispatchQueue.main.async {
      task()
    }
  }

  // Background Queue
  class func performTaskInBackground(task:@escaping () throws -> ()) {
    DispatchQueue.global(qos: .background).async {
      do {
        try task()
      } catch let error as NSError {
        print("error in background thread:\(error.localizedDescription)")
      }
    }
  }

  // Concurrent Queue
  class func perfromTaskInConcurrentQueue(task:@escaping () throws -> ()) {
    concurrentQueue.async {
      do {
        try task()
      } catch let error as NSError {
        print("error in Concurrent Queue:\(error.localizedDescription)")
      }
    }
  }

  // Serial Queue
  class func perfromTaskInSerialQueue(task:@escaping () throws -> ()) {
    serialQueue.async {
      do {
        try task()
      } catch let error as NSError {
        print("error in Serial Queue:\(error.localizedDescription)")
      }
    }
  }

  // Perform task afterDelay
  class func performTaskAfterDealy(_ timeInteval: TimeInterval, _ task:@escaping () -> ()) {
    DispatchQueue.main.asyncAfter(deadline: (.now() + timeInteval)) {
      task()
    }
  }
}

기본 대기열 사용을 보여주는 예.

override func viewDidLoad() {
    super.viewDidLoad()
     Threads.performTaskInMainQueue {
        //Update UI
    }
}


답변