Apple的iOS8發佈之後,你們都開始了適配的工做了。可是這個過程總會遇到一些攔路虎,例如推送的API改動。但是商業項目上嵌入了各類各樣的第三方靜態庫,這些靜態庫質量良莠不齊,其中一個靜態庫甚至在Xcode6上編譯後出現問題。因而只能使用Xcode5來編譯,但這樣就有一個很糾結的問題就是,UIMutableUserNotificationAction等一些類在舊版的Xcode要麼就是沒法編譯,要麼只能用宏來跳過。html
這時候,我仍是想起了Objective-C的運行時方法,使用NSClassFromString(@"UIMutableUserNotificationAction")來獲取到系統的類。光這樣子仍是有不少不足,由於這個類中有不少方法、屬性。雖然保證了運行的正常,可是編寫這些方法仍是有各類不便。例如各類performSelector:、objc_msgSend、setValue: forKey:,實在寫得很痛苦。我這裏用了一個比較取巧的方法,新建一個僞造的類如「XXXMutableUserNotificationAction」,繼承NSObject便可。而後將UIMutableUserNotificationAction全部的屬性和方法的聲明添加到XXXMutableUserNotificationAction的頭文件。之後,使用UIMutableUserNotificationAction時,就以下方:緩存
1 Class XXXMutableUserNotificationActionClass = NSClassFromString(@"UIMutableUserNotificationAction"); 2 XXXUIMutableUserNotificationAction *action = [[XXXMutableUserNotificationActionClass alloc] init];
既可使用Xcode的補全提示,又能夠經過編譯。(若是你們有更好的方法,歡迎探討探討)ide
Object-C運行時的方法當然強大,可是使用這些方法仍是有必定的風險。例如靜態分析對於一些運行時的問題是檢查不出來的,這裏我舉一個內存泄漏的例子。性能
ui
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 }];
先來看看這兩段代碼的區別只在於delegate的設置前後不同,但這就形成了後一段代碼在iOS6上就沒法觸發RAC裏方法,iOS7上正常。爲何呢?spa
這涉及到一個相似緩存的機制。平時,咱們會習慣使用respondsToSelector:來檢查一個對象或者類是否實現了對應的方法,但頻繁調用respondsToSelector:會對性能有必定的影響。特別是UITableView的dataSource一些方法,調用頻率很高的。所以,在設置delegate後,UIGestureRecognizer使用了respondsToSelector:檢查了一次self是否gestureRecognizer:shouldReceiveTouch:的方法,而後把這個結果緩存起來。因爲RAC也使用了相似Method Swizzling方法,所以在設置delegate之後再使用RAC的方法,UIGestureRecognizer也只讀取了緩存,並不會再次檢查,因此認爲self並未實現gestureRecognizer:shouldReceiveTouch:的方法,因而不做調用。(具體緩存的實現方法,能夠參照http://www.cnblogs.com/ipinka/p/3862786.html)code