iOS Development Stuff (iv) The dark arts of the OBJECTIVE-C runtime

Source: Internet
Author: User

I."Black Magic": Method Swizzling uses the runtime feature to replace the implementation of one approach with the implementation of another, or to use the four-dimensional understanding of runtime-to modify dispatch Table let the imp of a method correspond to our designated IMP.

two. Example Description : For example, we want to record the number of occurrences of each viewcontroller in an app.

three. Example Analysis :

  1. The first idea is that in the viewcontroller of the moment (viewdidappear) I use the recording tool to record a log.
    1 @implementationMyviewcontroller ()2 3- (void) Viewdidappear: (BOOL) Animated4 {5 [Super viewdidappear:animated];6 7     //Custom Code8 9     //LoggingTen [Logging logwitheventname:@ "My view did appear"]; One } A  -  -- (void) Mybuttonclicked: (ID) Sender the { -     //Custom Code -  -     //Logging + [Logging logwitheventname:@ "my button clicked"]; -}
    Methods of violence

    * The disadvantage is that I want to record all the VC then I will be in all the VC to write the code? That clever you will think of catagory. But think about it. You need to inherit Uiviewcontroller, Uitableviewcontroller, Uicollectionviewcontroller all of these VC add categories, And it violates the purpose of Apple's design catagory (to add some code to the class instead of replacing it)

  2. The second way of thinking is our protagonist method swizzling today.

three.Demo:

1 #import<objc/runtime.h>2 3 @implementationUiviewcontroller (Tracking)4 5+ (void) Load {6     //guaranteed to be replaced only once7     Staticdispatch_once_t Oncetoken;8Dispatch_once (&oncetoken, ^{9Classclass= [Selfclass];TenSEL Originalselector =@selector (viewwillappear:); OneSEL Swizzledselector =@selector (xxx_viewwillappear:); A  -Method Originalmethod = Class_getinstancemethod (class, originalselector); -Method Swizzledmethod = Class_getinstancemethod (class, swizzledselector); the  -BOOL Didaddmethod = -Class_addmethod (class, - Originalselector, + method_getimplementation (swizzledmethod), - method_gettypeencoding (Swizzledmethod)); +  A         if(didaddmethod) { atClass_replacemethod (class, - Swizzledselector, - method_getimplementation (originalmethod), - method_gettypeencoding (Originalmethod)); -}Else { - method_exchangeimplementations (Originalmethod, swizzledmethod); in         } -     }); to } +  - #pragmaMark-method swizzling the  *- (void) Xxx_viewwillappear: (BOOL) Animated { $     //Here we need to explain, because we need to call the implementation of the parent class in Viewwillappear. This line of code is called when the Xxx_viewwillappear and Viewwillappear methods have been replaced. So it's not a seemingly recursive form.Panax Notoginseng [self xxx_viewwillappear:animated]; -      the[Logging Logwitheventname:nsstringfromclass ([selfclass])];  + } A  the @end        
Add categories to Uiviewcontroller

Explanation 1. The only thing that may need to be explained here is class_addMethod . The first attempt to add the original selector is to do a layer of protection, because if the class is not implemented originalSelector , but its parent class implements it, it class_getInstanceMethod returns the method of the parent class. This method_exchangeImplementations replaces the method of the parent class, which is certainly not what you want. So we first try to add orginalSelector , if already exist, and then use the method_exchangeImplementations original method to implement the implementation of the new method to swap out

Explanation 2:swizzling always executes in +load, Because method swizzling affects global state, it's important to minimize the possibility of RAC E conditions. +load is guaranteed to being loaded during class initialization, which provides a modicum of consistency for changing system- Wide behavior. By contrast, +initialize provides no such guarantee of the when it'll be executed-in fact, it may never is called, if that C Lass is never messaged directly by the App.da probably means that because the square +load is guaranteed to be in the class initialization load, thus changing the system behavior provides a bit of consistency. By contrast, there is no guarantee of +init (), and if the app is not called directly, it may never be executed.

  

1 void(goriginalviewdidappear) (ID, SEL, BOOL);2 3 voidNewviewdidappear (Uiviewcontroller *Self , SEL _cmd, BOOL animated)4 {5     //Call Original Implementation6 goriginalviewdidappear (self, _cmd, animated);7 8     //Logging9[Logging Logwitheventname:nsstringfromclass ([selfclass])];Ten } One  A+ (void) Load - { -Method Originalmethod =Class_getinstancemethod (Self, @selector (viewdidappear:)); theGoriginalviewdidappear = (void*) method_getimplementation (Originalmethod); -  -     if(!Class_addmethod (Self, @selector (viewdidappear:), (IMP) newviewdidappear, method_gettypeencoding (Originalmethod ))) { - method_setimplementation (Originalmethod, (IMP) newviewdidappear); +     } -}
Instead of replacing the old method directly

Four. Summary : What is the dangers of Method swizzling in Objective C?

    • Method swizzling is not atomic
    • Changes behavior of un-owned code
    • Possible Naming conflicts
    • Swizzling changes the method ' s arguments
    • The Order of Swizzles matters
    • Difficult to understand (looks recursive)
    • Difficult to debug

iOS Development Stuff (iv) The dark arts of the OBJECTIVE-C runtime

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.