sourcecode

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

codebag 2023. 4. 13. 20:48
반응형

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

내 앱에는 NSRLSession을 만들고 NSURLRequest를 전송하는 기능이 있습니다.

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

이 태스크의 완료 블록에서는, 발신측 뷰 컨트롤러에 UIImage를 추가하는 계산을 실시할 필요가 있습니다.내 펑크가 있는데

func displayQRCode(receiveAddr, withAmountInBTC:amountBTC)

UIIMage 가산 연산을 합니다.완료 블록 내에서 뷰 추가 코드를 실행하려고 하면 백그라운드 처리 중에 레이아웃 엔진을 사용할 수 없다는 오류가 발생합니다.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" 및 "amountB" 파라미터를 추가하는 방법을 모릅니다.TC"를 선택합니다.이 작업을 어떻게 해야 합니까, 아니면 응용 프로그램의 메인 큐에 메서드 호출을 추가하는 최적의 방법을 제안할 수 있습니까?

최신 버전의 Swift 사용DispatchQueue.main.async메인 스레드에 디스패치하려면:

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

메인 큐에서 다음 명령을 사용합니다.

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

이전 버전의 Swift 사용:

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

Swift 3+ 및 Swift 4 버전:

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

Swift 3 및 Xcode 9.2:

dispatch_async_on_main_queue {
    print("Hello")
}

스위프트 2

Trailing Closures를 사용하면 다음과 같이 됩니다.

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

Trailing Closures(후행 폐쇄)는 Swift 구문설탕으로, 함수 파라미터 스코프 외부에 폐쇄를 정의할 수 있습니다.자세한 내용은 Swift 2.2 Programming Language Guide의 Trailing Closures를 참조하십시오.

dispatch_async의 경우 API는func dispatch_async(queue: dispatch_queue_t, _ block: dispatch_block_t)부터dispatch_block_t의 타입 에일리어스입니다.() -> Void- 0개의 파라미터를 수신하고 반환값을 가지지 않는 폐쇄이며, 블록은 함수의 마지막 파라미터로서 외부 스코프에서 폐쇄를 정의할 수 있습니다.dispatch_async.

컬렉션 다시 로드기본 스레드 보기

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

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

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

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

Async.main {
    // Your code here
}

적절한 방법은 다음 코드와 같이 main_queue에서 dispatch_async를 사용하는 것입니다.

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

를 사용하여 메인 스레드로 전환할 수 있습니다.

DispatchQueue.main.async {
        // UI Code Goes Here
    }

당신은 또한 다음 POP에 의해 my writing your custom protocol을 더 재사용 가능하고 읽을 수 있는 코드를 쓸 수 있습니다.

protocol MainThreadRunAble : AnyObject {}

확장을 사용한 프로토콜 구현

extension MainThreadRunAble {
func runOnMain(code : @escaping()->()) {
    DispatchQueue.main.async {
        code()
    }
}
func runOnMain(withDelay delay : Float ,code : @escaping()->()){
    DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
       code()
    }
}}

클래스를 메인 스레드에서 실행할 프로토콜에 준거합니다.

class YourClass : BaseClass,MainThreadRunAble{}

그 후, 요구에 따라서, 어느쪽인가를 호출합니다.

runOnMain {
        //update on main
    }
    runOnMain(withDelay: 1) {
    //update on main
    }

아키텍처 중 하나를 사용하고 있는 경우 뷰 컨트롤러만이 메인 스레드에서 실행할 수 있는 이 코드에 액세스할 수 있습니다.그 후 확장 기능을 구현합니다.

extension UIViewController {
func runOnMain(code : @escaping()->()) {
    DispatchQueue.main.async {
        code()
    }
}
func runOnMain(withDelay delay : Float ,code : @escaping()->()){
    DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
       code()
    }
}}

다음은 더 나은 구문을 위해 추가할 수 있는 작은 글로벌 함수입니다.

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

사용방법

dispatch_on_main {
    // Do some UI stuff
}
//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()
})

폐쇄의 내부에서 자신을 이용한다면 자신을 약하게 만드는 것을 잊지 마세요.

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

최신 Swift 코드(Swift 5.5+ 및 iOS 13+)의 경우, Apple은 보다 깨끗하고 성능적이며 안전한 코드를 위해 GCD가 아닌 주요 스레드 작업을 주연 배우에게 제안합니다.

여기에서는 배우를 이용하여 본선에 파견하는 4가지 방법을 자세히 설명했습니다.

은 문제의 입니다.@MainActor속성 래퍼

@MainActor func callFunctionOnMainThread(paramOne: Int, paramTwo: String) {
    // We can now access parameters on the main thread
}

이치노 async/await:

await callFunctionOnMainThread(paramOne: 2, paramTwo: "Two")

언급URL : https://stackoverflow.com/questions/24985716/in-swift-how-to-call-method-with-parameters-on-gcd-main-thread

반응형