Diffable DataSource队列线程疑问:为何else分支从未执行?
我希望深入理解Diffable DataSource的线程机制。我的代码在主线程创建了一个Diffable DataSource,该数据源使用一个后备存储,后备存储的数据来自以下getter方法:
var getData: [MyDataType] { get { //Sometimes this prints MainThread and sometimes it prints com.apple.uikit.datasource.diffing LOG.DLog("Returning Data On \(currentQueueName())") if Thread.isMainThread { return _myDataValues } else { //This else statement never enters return DispatchQueue.main.sync { LOG.DLog("Returning Data On Main") return _myDataValues } } } } func currentQueueName() -> String { let name = __dispatch_queue_get_label(nil) guard let str = String(cString: name, encoding: .utf8) else { return ""} return str }
当我的get方法执行时,有时队列名称是com.apple.uikit.datasource.diffing,有时是Main。在队列名称为com.apple.uikit.datasource.diffing的情况下,我预期会进入else分支,但它从未执行。因此我的问题是:为何代码示例中的else分支从未进入?我猜测Diffable串行队列是在创建Diffable DataSource的同一线程上创建的。
核心原因是:com.apple.uikit.datasource.diffing队列是运行在主线程上的串行队列。
你通过__dispatch_queue_get_label拿到的是当前执行的GCD队列名称,但Thread.isMainThread判断的是当前代码所在的线程——这个Diffable专用队列并没有创建新线程,而是直接复用了主线程来执行任务。
也就是说,当代码在com.apple.uikit.datasource.diffing队列上执行时,它依然处于主线程中,所以Thread.isMainThread始终返回true,自然不会进入else分支。
你的猜测方向是对的:Diffable DataSource的内部队列确实和创建它的线程(主线程)绑定,它只是在主线程上开辟了一个专用的串行队列来处理diff计算等逻辑,避免和主线程上的其他UI任务冲突,但线程本身还是主线程。
内容的提问来源于stack exchange,提问作者dubbeat

