iOS 在主執行緒操作UI不能保證安全

GabrielPanda發表於2018-10-15

先看一下SDWebImage的一段程式碼

#ifndef dispatch_queue_async_safe
#define dispatch_queue_async_safe(queue, block)\
    if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(queue)) {\
        block();\
    } else {\
        dispatch_async(queue, block);\
    }
#endif

#ifndef dispatch_main_async_safe
#define dispatch_main_async_safe(block) dispatch_queue_async_safe(dispatch_get_main_queue(), block)
#endif

複製程式碼

是不是很奇怪,一般來說下面的程式碼就足夠了啊,可以保證在主執行緒執行

if ([NSThread isMainThread]) {
       block();
} else {
   dispatch_async(dispatch_get_main_queue(), ^{
       block();
   })
}

複製程式碼

github issues上看到下面的討論:


24025596: MapKit: It's not safe to call MKMapView's addOverlay on a non-main-queue, even if it is executed on the main thread #7053

在非主佇列中呼叫MKMapView的 addOverlay方法是不安全的,即使是在主執行緒,也有可能造成崩潰。

@NachoSoto I contacted Apple DTS, they confirmed it is a bug in MapKit. But they also cautioned that the pattern of dispatch_sync and the isMainThread will likely run into more issues like this and the one reported by @laptobbe above.

They also explicitly stated that main queue and the main thread are not the same thing, but are have subtle differences, as shown in my demo app.

UI 主執行緒執行不一定安全.png

在主佇列中的任務,一定會放到主執行緒執行 所以只要是在主佇列中的任務,既可以保證在主佇列,也可以保證在主執行緒中執行。所以就可以通過判斷當前佇列是不是主佇列來代替判斷當前執行任務的執行緒是否是主執行緒,這樣會更加安全。

相關文章