Skip to content

Latest commit

 

History

History
99 lines (81 loc) · 2.23 KB

SafeMainAsync.md

File metadata and controls

99 lines (81 loc) · 2.23 KB

很多时候需要返回主线程执行操作,此时最简单粗暴的方式就是直接

// OC
dispatch_async(dispatch_get_main_queue(), ^{
	// code
});
// Swift
DispatchQueue.main.async {
	// code
}

但是这样并不友好,比如当前如果已经时主线程,所以就有了safe的形式

// OC 早期SDWebImage
#define dispatch_main_sync_safe(block)
	if ([NSThread isMainThread]) {
		block();
	} else {
		dispatch_sync(dispatch_get_main_queue(), block);
	}
#define dispatch_main_async_safe(block)
	if ([NSThread isMainThread]) {
		block();
	} else {
		dispatch_async(dispatch_get_main_queue(), block);
	}

// Swift 早期Kingfisher
extension DispatchQueue {
    func safeAsync(_ block: @escaping ()->()) {
        if self === DispatchQueue.main && Thread.isMainThread {
            block()
        } else {
            async { block() }
        }
    }
}

后来有人遇到主线程非主队列issue

所以后来SDWebImage中更改了判断方式

// OC SDWebImage
#ifndef dispatch_main_async_safe
#define dispatch_main_async_safe(block)
    if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(dispatch_get_main_queue())) {
        block();
    } else {
        dispatch_async(dispatch_get_main_queue(), block);
    }
#endif

Kingfisher中貌似没改

理应这个样子

// Swift 自己瞎写的,认真你就输了
import Foundation

extension DispatchQueue {

    fileprivate static var currentQueueLabel: String? {
        let cString = __dispatch_queue_get_label(nil)
        return String(cString: cString)
    }

    fileprivate static var isMainQueue: Bool {
        return currentQueueLabel == self.main.label
    }
}

func ddyMainAsyncSafe(_ execute: @escaping () -> Void) {
    DispatchQueue.isMainQueue ? execute() : DispatchQueue.main.async(execute: execute)
}

附加一个RxSwift中的判断方式

extension DispatchQueue {
    private static var token: DispatchSpecificKey<()> = {
        let key = DispatchSpecificKey<()>()
        DispatchQueue.main.setSpecific(key: key, value: ())
        return key
    }()

    static var isMain: Bool {
        return DispatchQueue.getSpecific(key: token) != nil
    }
}