消息機(jī)制 - 調(diào)用私有方法
OC的runtime特性虑瀑,使其沒(méi)有嚴(yán)格意義上的私有方法情屹。
objc_getClass()
sel_registerName()
objc_msgSend()
例:
@interface MyObjcet : NSObject
@end
@implementation MyObjcet
- (void)myFunction
{
NSLog(@"myFunction");
}
@end
//即使myFunction方法沒(méi)有通過(guò).h暴露出來(lái),也是可以調(diào)用成功的嚷兔。
MyObjcet *obj = [MyObjcet new];
objc_msgSend(obj, sel_registerName("myFunction"));
方法交換
很多時(shí)候森渐,我們想要對(duì)系統(tǒng)框架的某些方法添加一些自定義邏輯。繼承是個(gè)解決辦法冒晰,但得改代碼同衣,如何盡可能少的侵入項(xiàng)目呢?
class_getClassMethod()
class_getInstanceMethod()
method_exchangeImplementations()
例: NSMutableDictionary的setObject:forKey:方法壶运,當(dāng)obj為nil的時(shí)候就會(huì)拋異常耐齐。多寫幾個(gè)if其實(shí)也ok,可是...
+ (void)load
{
Class clas = [object_getClass([NSMutableDictionary dictionary]) class];
Method original = class_getInstanceMethod(clas, @selector(setObject:forKey:));
Method new = class_getInstanceMethod(clas, @selector(he_setObject:forKey:));
method_exchangeImplementations(original, new);
}
@implementation NSMutableDictionary (HECrashHandle)
- (void)he_setObject:(id)anObject forKey:(id<NSCopying>)aKey{
if(aKey == nil) return;
if(anObject == nil){
[self removeObjectForKey:aKey];
}else{
[self he_setObject:anObject forKey:aKey];
}
}
@end
分類中添加屬性
分類的初衷是為擴(kuò)展方法而存在的蒋情,但很多時(shí)候我們需要在分類中添加屬性以滿足需求埠况。
objc_setAssociatedObject()
objc_getAssociatedObject()
例: 為UIView添加屬性myDesc
@interface UIView (Desc)
@property NSString *myDesc;
@end
@implementation UIView (Desc)
- (NSString *)myDesc
{
return objc_getAssociatedObject(self, _cmd);
}
- (void)setMyDesc:(NSString *)myDesc
{
objc_setAssociatedObject(self, @selector(myDesc), myDesc, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
@end
添加方法
這個(gè)我這沒(méi)怎么用上,如果有好的使用場(chǎng)景棵癣,歡迎在下方的評(píng)論區(qū)一起交流
resolveClassMethod:
resolveInstanceMethod:
class_addMethod()
示例:
void myMethodIMP(id self, SEL _cmd) { .... }
@implementation MyClass
+ (BOOL)resolveInstanceMethod:(SEL)aSEL
{
if (aSEL == @selector(resolveThisMethodDynamically)) {
class_addMethod([self class], aSEL, (IMP) dynamicMethodIMP, "v@:");
return YES;
}
return [super resolveInstanceMethod:aSEL];
}
@end