Swift에서 GCD 메인 스레드에서 매개 변수가있는 메소드를 호출하는 방법은 무엇입니까?


192

내 응용 프로그램에는 NSRURLSession을 만들고 NSURLRequest를 사용하여 보내는 기능이 있습니다.

sesh.dataTaskWithRequest(req, completionHandler: {(data, response, error)

이 작업의 완료 블록에서 UIView를 호출하는 뷰 컨트롤러에 추가하는 계산을 수행해야합니다. 나는 func라는 기능이 있습니다

func displayQRCode(receiveAddr, withAmountInBTC:amountBTC)

UIImage-adding 계산을 수행합니다. 완료 블록 내에서 뷰 추가 코드를 실행하려고하면 Xcode에서 백그라운드 프로세스 중에 레이아웃 엔진을 사용할 수 없다는 오류가 발생합니다. 그래서 메인 스레드에서 메소드를 대기열에 넣는 SO 코드가 있습니다.

let time = dispatch_time(DISPATCH_TIME_NOW, Int64(0.0 * Double(NSEC_PER_MSEC)))

dispatch_after(time, dispatch_get_main_queue(), {
    let returned = UIApplication.sharedApplication().sendAction("displayQRCode:", to: self.delegate, from: self, forEvent: nil)
})

그러나 매개 변수 "receiveAddr"및 "amountBTC"를이 함수 호출에 추가하는 방법을 모르겠습니다. 이 작업을 어떻게 수행하거나 누군가가 응용 프로그램의 기본 대기열에 메소드 호출을 추가하는 최적의 방법을 제안 할 수 있습니까?

답변:


497

최신 버전의 Swift DispatchQueue.main.async는 기본 스레드로 디스패치하는 데 사용 됩니다.

DispatchQueue.main.async { 
  // your code here
}

메인 큐에서 파견 하려면 다음 을 사용하십시오.

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
  // your code here
}

이전 버전의 스위프트는 다음을 사용했습니다.

dispatch_async(dispatch_get_main_queue(), {
  let delegateObj = UIApplication.sharedApplication().delegate as YourAppDelegateClass
  delegateObj.addUIImage("yourstring")
})

귀하의 제안이 효과가 있다고 생각하지만 UIApplication.sharedApplication을 호출하지 않기 때문에 내 대답이 약간 더 낫다고 생각합니다. 내 대답의 범위는 중요한 대상으로 제한되는 반면, 귀하는 내가하는 일을 정확하게 배우기 위해 더 많은 문서를 읽을 필요가있는 보조 대상을 가져옵니다. 그리고 올바른 함수 호출을 포함하도록 원래 질문을 편집했습니다. 나는 displayQRCode가 충분히 구체적이지 않다고 생각했지만 우리의 의견으로는 지금입니다. 지적 해 주셔서 감사합니다.
almel

84

스위프트 3+ 및 스위프트 4 버전 :

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

스위프트 3 및 Xcode 9.2 :

dispatch_async_on_main_queue {
    print("Hello")
}

15

스위프트 2

후행 폐쇄를 사용하면 다음과 같이됩니다.

dispatch_async(dispatch_get_main_queue()) {
    self.tableView.reloadData()
}

후행 폐쇄는 기능 매개 변수 범위 밖에서 폐쇄를 정의 할 수있는 스위프트 구문 설탕입니다. 자세한 내용은 Swift 2.2 프로그래밍 언어 안내서의 후행 폐쇄 를 참조하십시오 .

dispatch_async의 경우 API는 func dispatch_async(queue: dispatch_queue_t, _ block: dispatch_block_t)이후 dispatch_block_t에 대한 별칭입니다. () -> Void-0 개의 매개 변수를 수신하고 리턴 값이없는 클로저이며 함수의 마지막 매개 변수 인 블록은 외부 범위에서 클로저를 정의 할 수 있습니다 dispatch_async.


1
그것은 내가 찾고있는 3 줄이었습니다 ... 이제 당신은 내 마음을 읽는 것을 멈출 수 있습니다
Laszlo

8

메인 스레드에서 collectionView 다시로드

DispatchQueue.main.async {
    self.collectionView.reloadData()
}

7

다음은 다른 답변과 동일한 결과를 얻는 더 좋은 (IMO) Swifty / Cocoa 스타일 구문입니다.

NSOperationQueue.mainQueue().addOperationWithBlock({
    // Your code here
})

또는 인기있는 Async Swift 라이브러리를 사용 하여 코드를 줄이고 기능을 향상시킬 수 있습니다.

Async.main {
    // Your code here
}

방법의 이름이OperationQueue.main.addOperation({ }
Frostmourne

3

이를 수행하는 올바른 방법은 다음 코드에서와 같이 main_queue에서 dispatch_async를 사용하는 것입니다.

dispatch_async(dispatch_get_main_queue(), {
    (self.delegate as TBGQRCodeViewController).displayQRCode(receiveAddr, withAmountInBTC:amountBTC)
})

2

보다 멋진 구문을 위해 추가 할 수있는 멋진 전역 함수가 있습니다.

func dispatch_on_main(block: dispatch_block_t) {
    dispatch_async(dispatch_get_main_queue(), block)
}

그리고 사용법

dispatch_on_main {
    // Do some UI stuff
}

2
//Perform some task and update UI immediately.
DispatchQueue.global(qos: .userInitiated).async {  
    // Call your function here
    DispatchQueue.main.async {  
        // Update UI
        self.tableView.reloadData()  
    }
}

//To call or execute function after some time
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
    //Here call your function
}

//If you want to do changes in UI use this
DispatchQueue.main.async(execute: {
    //Update UI
    self.tableView.reloadData()
})

2

클로저 내부에서 자체를 사용하는 경우 자신을 약화시키는 것을 잊지 마십시오.

dispatch_async(dispatch_get_main_queue(),{ [weak self] () -> () in
    if let strongSelf = self {
        self?.doSomething()
    }
})

1
왜 우리가 이것을해야하는지 설명해 주시겠습니까?
Jackspicer

메모리 사이클을 생성 할 수 있기 때문입니다. 즉, 무언가에 대한 강한 참조가 있고 나에 대한 강한 참조가 있습니다. 우리 둘 다 메모리 힙을 떠날 수 없다는 것을 의미합니다.
jackofallcode
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.