After Apple's iOS 8 was released, Everyone began to adapt. However, this process will always encounter some obstacles, such as API changes pushed. However, a variety of third-party static libraries are embedded in commercial projects. The quality of these static libraries is uneven. One of these static libraries is even problematic after being compiled on xcode6. Therefore, xcode5 can only be used for compilation, but there is a very tangled problem that some classes such as uimutableusernotificationaction cannot be compiled in the old version of xcode or can only be skipped using macros.
At this time, I think of the objective-C Runtime method, using nsclassfromstring (@ "uimutableusernotificationaction") to get the system class. There are still many shortcomings in this case, because there are many methods and attributes in this class. Although the operation is normal, it is inconvenient to compile these methods. For example, it is very painful to write a variety of javasmselector:, objc_msgsend, and setvalue: forkey. Here I use a clever method to create a forged class such as "xxxmutableusernotificationaction" and inherit nsobject. Add all attributes and method declarations of uimutableusernotificationaction to the header file of xxxmutableusernotificationaction. In the future, when uimutableusernotificationaction is used, it is as follows:
1 Class XXXMutableUserNotificationActionClass = NSClassFromString(@"UIMutableUserNotificationAction");2 XXXUIMutableUserNotificationAction *action = [[XXXMutableUserNotificationActionClass alloc] init];
You can use the complete prompts of xcode and compile it. (If you have a better method, you are welcome to discuss it)
Although object-C Runtime methods are powerful, there are still some risks when using these methods. For example, static analysis cannot check some running problems. Here is an example of Memory leakage. In my project, I used some methods to add attributes at runtime, and added block attributes for some views. When using self directly in the block, memory leakage that cannot be checked by the compiler will occur. Leakage path: VC-> View-> block-> VC, forming a circular reference. This type of leakage is relatively concealed, but it may be impossible for the children's shoes that often use RAC to attack hundreds of viruses (^_^ ). Because @ weakify and @ strongify are frequently used, I am sensitive to this type of leakage. _ Weak typeof (Self) weakself = self is an ugly but effective method. If you are interested, you can refer to the RAC solution, which is essentially the same.
Aside from the question, blockkit contains a very useful Classification "nsobject + bkassociatedobjects", which can be used to add attributes during runtime in a more friendly way. The implementation idea of bk_weaklyassociatevalue is quite clever, it is worth learning.
The last tip is about the relationship between RAC and system APIs. Let's take a look at the two sections of code:
1 UIGestureRecognizer *dismissKeyboardGR = [[UIGestureRecognizer alloc] init];2 [self.view addGestureRecognizer:dismissKeyboardGR];3 [[[self rac_signalForSelector:@selector(gestureRecognizer:shouldReceiveTouch:)4 fromProtocol:@protocol(UIGestureRecognizerDelegate)]5 takeUntil:dismissKeyboardGR.rac_willDeallocSignal]6 subscribeNext:^(id x) {7 [Utils hideKeyboardInAllView];8 }];9 dismissKeyboardGR.delegate = self;
1 UIGestureRecognizer *dismissKeyboardGR = [[UIGestureRecognizer alloc] init];2 [self.view addGestureRecognizer:dismissKeyboardGR];3 dismissKeyboardGR.delegate = self;4 [[[self rac_signalForSelector:@selector(gestureRecognizer:shouldReceiveTouch:)5 fromProtocol:@protocol(UIGestureRecognizerDelegate)]6 takeUntil:dismissKeyboardGR.rac_willDeallocSignal]7 subscribeNext:^(id x) {8 [Utils hideKeyboardInAllView];9 }];
The difference between the two codes is that the delegate settings are different, but this makes the later code in ios6 unable to trigger the RAC method, and ios7 is normal. Why?
This involves a mechanism similar to caching. At ordinary times, we will get used to using respondstoselector: to check whether an object or class has implemented the corresponding method, but the frequent call of respondstoselector: will have a certain impact on the performance. In particular, the datasource of uitableview is frequently called. Therefore, after delegate is set, uigesturerecognizer uses respondstoselector: checks whether self is a gesturerecognizer: shouldreceivetouch method, and then caches the result. Because RAC uses a method similar to the swizzling method, the RAC method is used after delegate is set. uigesturerecognizer only reads the cache and does not check it again. Therefore, it is considered that self does not implement gesturerecognizer: shouldreceivetouch: method, so it is not called. (Specific cache implementation method, you can refer to the http://www.cnblogs.com/ipinka/p/3862786.html)
Objective-C Running Skills