In daily development, we often register some notices and initiate some requests. When we don’t need them, we should cancel the notices and requests in time. Otherwise, there may be problems or crashes. For example, we will register some notifications in the viewdidload of the controller, and then log off the notifications in dealloc. Or when we exit the controller, cancel all currently initiated requests. This is very common in MRC development, because when the request returns, the callback agent may be a wild pointer. This manual logoff method is a little cumbersome. It is often forgotten in development, resulting in the problem being hidden. Because of this, we hope to provide a framework to automatically solve the call of such logout notification and cancellation request.
By analyzing this scenario, we can find that the life cycle of these notification observers and requests depends on a host. When a host object is destroyed, the observer and the request are also destroyed. That is, the timing of automatically calling logoff determines dealloc when the object is released. At the same time, we should not have special requirements for the type of host. The host may be a controller, a user-defined control, or a data module, that is, the host is an object of type nsobject. In addition, we hope to customize the operations during logoff, such as logoff event observation or cancellation request. The above are the most basic requirements for this architecture. In addition, we have some higher requirements. We hope that the impact of the architecture on performance will be as small as possible to avoid some circular reference problems. It should be simple to use, and it is best to have some management functions.
Compared with other requirements, capturing the release time of nsobject objects is the most critical requirement. We usually think of using method swizzling to replace the dealloc method of nsobject. But here are a few issues to note.
1. Under arc development, dealloc is used as the keyword, and the compiler is limited. A compilation error “arc forbids use of ‘dealloc’ in a @ selector” will be generated. However, we can solve it in the run-time way.
2. Dealloc is one of the most basic and frequently called methods. If this method is replaced, one is that the introduction of code has too much impact on the project, and the other is that it is expensive to implement. Because most dealloc operations do not need to introduce automatic logoff, it is inappropriate to correct all executions for a few requirements.
Therefore, method swizzling can be used as the final alternative, but it is not suitable as the first choice.
Another idea is to embed our own objects in the host release process, so that our objects can be released together when the host releases, so as to obtain the time point of dealloc. Obviously, associatedobject is the solution we want. Compared with the method swizzling scheme, the associatedobject scheme has a smaller impact on the project, and only objects that are automatically logged off will incur costs.
In view of the above comparison, we build a release notification object, connect it to the host object through the associatedobject method, and call back when the host releases to complete the logout action.
The following is the declaration of the release notification class rfdestorynotify. Add destruction listening to the host object through rfdestorynotifysetname method, and call back the specific logout method through block.
Before using rfdestorynotify, you need to understand the timing characteristics of the whole release process before you can write appropriate code. Therefore, we first write the following code for debugging.
We add four callbacks in the host release function dealloc (33), release listening callback (58), host release (61), and after host release (62). After debugging, the trigger sequence is as follows:
The whole release process is synchronous, and the host s first_ Release the owner, release the associated rfdestorynotify object, and then trigger the callback rfdestorynotifyblock to complete the whole process.
From the timing point of view, the callback rfdestorynotifyblock is in the host s_ After the release action of owner, but the host s_ The owner is still alive, so you can know the host s_ All the object members held by the owner have been released, but the member values of the basic type are still retained. From the debugging results, it is also true.
Therefore, we can know that when releasing the callback, the object member held by the host is unreliable, but the memory address of the host is reliable. This is why we added userinfo to rfdestorynotify.
The above is the result of debugging. We’d better confirm it from the source code level of OC.
The above is the processing of OC object destruction. After searching the data, the object is found_ Cxxdestruct is responsible for traversing the held objects and destructing them_ object_ remove_ Assocations is responsible for destroying the associated objects. Cleardeallocating is responsible for setting nil for the reference of this object held by weak. From the perspective of code, the timing of code execution is also consistent with that of debugging. This also proves that the running characteristics of rfdestorynotify described above are correct and reliable.
Dealloc process under arc and. Cxx_ Exploration of destruct
At present, this design has been widely used in our app project. By introducing rfevent, the corresponding event observation can be automatically cancelled when the observer is released. This design is introduced into the network transaction request work, which can declare two different life cycles: global and host. It is convenient to manage network requests and enhance the robustness of the program. This design is introduced into the custom dialog, which can easily destroy the dialog created by the host during fallback, and facilitate the automatic page Jump. From the practical effect, the improvement of development efficiency and code quality is still very obvious. Therefore, I recommend you, hoping to play a positive role in your future development work.