[swift] 작업이 완료 될 때까지 대기

DispatchQueue의 작업이 완료 될 때까지 코드를 기다리게하려면 어떻게해야합니까? CompletionHandler 또는 무언가가 필요합니까?

func myFunction() {
    var a: Int?

    DispatchQueue.main.async {
        var b: Int = 3
        a = b
    }

    // wait until the task finishes, then print 

    print(a) // - this will contain nil, of course, because it
             // will execute before the code above

}

저는 Xcode 8.2를 사용하고 있으며 Swift 3로 작성하고 있습니다.



답변

DispatchGroup이를 위해 s를 사용하십시오 . 그룹 enter()leave()통화가 균형을 이룰 때 알림을받을 수 있습니다 .

func myFunction() {
    var a: Int?

    let group = DispatchGroup()
    group.enter()

    DispatchQueue.main.async {
        a = 1
        group.leave()
    }

    // does not wait. But the code in notify() gets run 
    // after enter() and leave() calls are balanced

    group.notify(queue: .main) {
        print(a)
    }
}

또는 기다릴 수 있습니다.

func myFunction() {
    var a: Int?

    let group = DispatchGroup()
    group.enter()

    // avoid deadlocks by not using .main queue here
    DispatchQueue.global(attributes: .qosDefault).async {
        a = 1
        group.leave()
    }

    // wait ...
    group.wait()

    print(a) // you could also `return a` here
}

참고 : group.wait()현재 대기열 (아마도 귀하의 경우 기본 대기열)을 차단하므로 교착 상태dispatch.async 를 피하기 위해 다른 대기열 (위 샘플 코드와 같음)에 있어야합니다 .


답변

Swift 3에서는 DispatchQueue하나의 작업 을 완료 할 때 완료 핸들러가 필요하지 않습니다 . 또한 다양한 방법으로 목표를 달성 할 수 있습니다.

한 가지 방법은 다음과 같습니다.

    var a: Int?

    let queue = DispatchQueue(label: "com.app.queue")
    queue.sync {

        for  i in 0..<10 {

            print("Ⓜ️" , i)
            a = i
        }
    }

    print("After Queue \(a)")

루프가 끝날 때까지 기다릴 것이지만이 경우 메인 스레드가 차단됩니다.

다음과 같이 동일한 작업을 수행 할 수도 있습니다.

    let myGroup = DispatchGroup()
    myGroup.enter()
    //// Do your task

    myGroup.leave() //// When your task completes
     myGroup.notify(queue: DispatchQueue.main) {

        ////// do your remaining work
    }

마지막으로 작업이 DispatchQueue를 사용하여 완료 될 때 완료 핸들러를 사용하려면 DispatchWorkItem.

다음은 사용 방법의 예입니다 DispatchWorkItem.

let workItem = DispatchWorkItem {
    // Do something
}

let queue = DispatchQueue.global()
queue.async {
    workItem.perform()
}
workItem.notify(queue: DispatchQueue.main) {
    // Here you can notify you Main thread
}


답변

디스패치 그룹 사용

   dispatchGroup.enter()
   FirstOperation(completion: { _ in
dispatchGroup.leave()
  })
    dispatchGroup.enter()
    SecondOperation(completion: { _ in
dispatchGroup.leave()
  })
   dispatchGroup.wait() //Waits here on this thread until the two operations complete executing.


답변

솔루션의 Swift 5 버전

func myCriticalFunction () {var value1 : 문자열? var value2 : 문자열?

let group = DispatchGroup()


group.enter()
//async operation 1
DispatchQueue.global(qos: .default).async { 
    // Network calls or some other async task
    value1 = //out of async task
    group.leave()
}


group.enter()
//async operation 2
DispatchQueue.global(qos: .default).async {
    // Network calls or some other async task
    value2 = //out of async task
    group.leave()
}


group.wait()

print("Value1 \(value1) , Value2 \(value2)") 

}


답변

스위프트 4

이러한 상황에 Async Function을 사용할 수 있습니다. 를 사용 DispatchGroup()하면 가끔 교착 상태 가 발생할 수 있습니다.

var a: Int?
@objc func myFunction(completion:@escaping (Bool) -> () ) {

    DispatchQueue.main.async {
        let b: Int = 3
        a = b
        completion(true)
    }

}

override func viewDidLoad() {
    super.viewDidLoad()

    myFunction { (status) in
        if status {
            print(self.a!)
        }
    }
}


답변