메인 스레드에서 메서드를 호출합니까?


82

우선 아이폰 용 코드를 작성하고 있습니다. 을 사용하지 않고 주 스레드에서 메서드를 호출 할 수 있어야합니다 performSelectorOnMainThread. 사용하고 싶지 않은 이유는 performSelectorOnMainThread단위 테스트를 위해 모의를 만들려고 할 때 문제가 발생하기 때문입니다.

[self performSelectorOnMainThread:@Selector(doSomething) withObject:nil];

문제는 내 모의가 호출하는 방법을 알고 doSomething있지만 호출하는 방법을 모른다는 것입니다 performSelectorOnMainThread.

그래서 어떤 해결책?

답변:


272

목표 -C

dispatch_async(dispatch_get_main_queue(), ^{
    [self doSomething];
});

빠른

DispatchQueue.main.async {
    self.doSomething()
}

레거시 스위프트

dispatch_async(dispatch_get_main_queue()) {
    self.doSomething()
}

당신은 방금 빠른 3 코드로 하루를 보냈습니다. 감사!
Felipe Balduino 2016

self를 블록에 직접 사용하지 않는 것이 좋습니다. 대신 약한 참조를 사용하십시오.
Jageen

2

소프트웨어에는 간접적 계층을 추가하면 거의 모든 것이 수정된다는 말이 있습니다.

doSomething 메소드가 실제 Something 작업을 수행하기 위해 really_doSomething 메소드를 호출하기 위해 performSelectorOnMainThread 만 수행하는 간접 쉘이되도록하십시오. 또는 doSomething 메서드를 변경하지 않으려면 모의 테스트 단위에서 doSomething_redirect_shell 메서드를 호출하여 유사한 작업을 수행하도록합니다.


1

Swift에서이를 수행하는 더 좋은 방법은 다음과 같습니다.

runThisInMainThread { () -> Void in
    // Run your code
    self.doSomething()
}

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

내 저장소에 표준 기능으로 포함되어 있습니다. https://github.com/goktugyil/EZSwiftExtensions


이것은 어떤 식 으로든 더 좋지 않습니다. 당신은 다른 것을 호출하는 것 외에는 아무것도하지 않는 함수를 만들었습니다. 스위프트 신택스 더욱 간략화 할 수있는 방법으로 '() ->에 보이드 "불필요
aryaxt

더 인간이 읽기 / 쓰기 가능합니다. 예 자동 완성은 "()-> Void in"에 추가됩니다. 어쨌든 void> void 클로저 에서이 자동 완성 동작을 비활성화 할 수 있습니까?
Esqarrouth 2015

당신이 가진 메소드 이름은 오해의 소지가있을 수 있으며, 블록이 메인 스레드에서 즉시 실행되는 것처럼 들리지만 사실이 아닙니다. 메인 큐의 dispatch_async는 다음 런 루프에 코드 블록을 추가합니다.이 중요한 동작은 "runThisInMainThread
aryaxt

1
이것은 예상되는 동작입니다. dispatch_async는 대기열 끝에 코드를 추가합니다. 즉시 호출되도록하려면 dispatch_sync를 대신 수행해야합니다. 이미있는 스레드의 큐에서 dispatch_sync를 수행하면 스레드 잠금이 발생합니다. 귀하의 예에서 인쇄 순서는 "a", "c", "b"입니다. a와 c는 동일한 범위에 있기 때문에 1 개의 runloop에서 실행됩니다. B 대기열에있는 기존의 다른 항목이 완료 나중에 때 가끔 호출 될 수 있도록 큐의 끝에 추가됩니다
aryaxt

1
@Esqarrouth- dispatch_async호출 후 차단 된 코드 가 확실 합니까? 사용의 요점은 뒤에 오는 것을 차단하지 않는 asyncsync입니다. (물론, 요청 된 코드의 요점이 메인 스레드 에서 실행되는 것이기 때문에 blockof 코드 는 메인 스레드의 다른 모든 것을 차단 합니다. 백그라운드 코드를 실행하려면 다른 큐를 요청해야합니다. 아니 dispatch_get_main_queue.)
ToolmakerSteve

1

그리고 이제 Swift 3에서 :

DispatchQueue.main.async{
   self.doSomething()
}

-4
// Draw Line
    func drawPath(from polyStr: String){
        DispatchQueue.main.async {
            let path = GMSPath(fromEncodedPath: polyStr)
            let polyline = GMSPolyline(path: path)
            polyline.strokeWidth = 3.0
            polyline.strokeColor = #colorLiteral(red: 0.05098039216, green: 0.5764705882, blue: 0.2784313725, alpha: 1)
            polyline.map = self.mapVu // Google MapView
        }

    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.