When we first started learning iOS, we were told that UI operations must be performed on the main thread. This is because UIKit methods are not thread-safe, and ensuring thread safety requires a lot of overhead. So the question is, is it safe to perform UI operations in the main thread? Obviously, the answer is no! In Apple's MapKit framework, there is a method called addOverlay, which requires the code to be executed not only on the main thread but also on the main queue of GCD when it is implemented at the bottom layer. This is an extremely rare problem, but someone has already encountered this problem when using ReactiveCocoa and submitted an issue. Apple's Developer Technology Support admitted that this is a bug. Regardless of whether this is a bug or a legacy design, or whether it is just a quibble, in order to avoid falling into the same trap again, I think it is necessary to analyze the cause of the problem and the solution. GCD knowledge review In GCD, the main queue can be obtained by using the dispatch_get_main_queue() function. Calling the dispatch_sync() method will synchronously submit the task to the specified queue. Note the difference between queues and threads. There is no "ownership relationship" between them. When we submit a task synchronously, we first block the current queue, and then wait until the next runloop to execute the block in the appropriate thread. Before executing a block, it will first look for a suitable thread to execute the block, and then block the thread until the block is executed. The rule for finding threads is: any block submitted to the main queue will be executed in the main thread. Under the premise of not violating this rule, the document also tells us that the system will automatically optimize and execute the block in the current thread as much as possible. By the way, the sufficient condition for GCD deadlock is: "repeatedly submitting blocks to the current queue synchronously". In principle, the cause of the deadlock is that the submitted block blocks the queue, and after the queue is blocked, dispatch_sync() can never be completed. It can be seen that this has nothing to do with the thread where the code is located. Another example can also prove this point. In the main thread, a block is synchronously dispatched to a serial queue. According to the principle of thread selection above, the block will be executed in the main thread, but it will not cause deadlock:
Cause Analysis After all this talk, let's get back to the bug described earlier. Now we know that even if the code is executed in the main thread, it is likely not running in the main queue (and vice versa). If we call MapKit's addOverlay method in a subqueue, even if it is currently in the main thread, it will cause a bug because the underlying implementation of this method determines the main queue rather than the main thread. Thinking further, sometimes in order to ensure that UI operations run on the main thread, if there is a function that can be used to create a new UILabel, in order to ensure thread safety, the code may be like this:
Strictly speaking, this way of writing is not 100% safe, because we cannot know whether the relevant system methods have the above bugs. Solution Since the block submitted to the main queue must be run in the main thread, and thread switching in GCD is usually caused by specifying a queue, we can make a more rigorous judgment, that is, to judge whether it is in the main queue instead of whether it is in the main thread. GCD does not provide an API to make corresponding judgments, but we can find another way to use the dispatch_queue_set_specific and dispatch_get_specific methods to mark the main queue:
Use the isMainQueue method instead of [NSThread isMainThread] to get better safety. References 1.Community bug reports about MapKit http://t.cn/RtxivSc 2.GCD's Main Queue vs Main Thread http://t.cn/RthOawx 3. Similar pitfalls encountered in ReactiveCocoa http://t.cn/RtxJFRX 4.Why can't we use a dispatch_sync on the current queue? http://t.cn/RtxJgPi |
<<: RecyclerView implements sliding deletion and dragging functions
>>: Android Studio template file group
What is a hot product? Not only do we need to mak...
Since 2020, many new brands and companies have be...
When visiting museums, we often see a large numbe...
The "Report on the Nutrition and Chronic Dis...
Companies can proactively send messages to employ...
We talk about optimizing creativity every day, bu...
In 2021, Xiaohongshu has been very active. Not on...
How much does it cost to attract investment in th...
A study published in Nature on December 22 analyz...
Why is there no traffic in your live broadcast ro...
Today, there was news online that "WeChat ha...
Produced by: Science Popularization China Author:...
Let’s start today’s official content! 1. Activity...
The idea of increasing order volume is shown in...