runtime
2018-08-14 本文已影响8人
西门淋雨
给NSObject增加属性
#import <Foundation/Foundation.h>
@interface NSObject (runtime)
@property(nonatomic,strong)NSString *myTitle;
@end
#import "NSObject+runtime.h"
#import <objc/runtime.h>
static NSString *const kName = @"kName";
static NSString *const kTitle = @"kTitle";
@implementation NSObject (runtime)
- (void)setMyTitle:(NSString *)myTitle{
objc_setAssociatedObject(self, &kTitle, myTitle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSString *)myTitle{
return objc_getAssociatedObject(self, &kTitle);
}
@end
弹框
#import <UIKit/UIKit.h>
typedef void (^AlertCallBlock)(NSInteger buttonIndex);
@interface UIAlertView (runtime)
- (void)showAlertWithBlock:(AlertCallBlock)block;
@end
#import "UIAlertView+runtime.h"
#import <objc/runtime.h>
static NSString *const kBlockKey = @"kBlockKey";
@implementation UIAlertView (runtime)
- (void)showAlertWithBlock:(AlertCallBlock)block{
self.delegate = self;
objc_setAssociatedObject(self, &kBlockKey, block, OBJC_ASSOCIATION_COPY);
[self show];
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
//根据给定的键从某对象中获取相应的关联对象值
AlertCallBlock alertCallBack = objc_getAssociatedObject(self, &kBlockKey);
if (alertCallBack) {
alertCallBack(buttonIndex);
objc_setAssociatedObject(self, &kBlockKey, nil, OBJC_ASSOCIATION_COPY);
}
}
@end
Method Swizzling方法交换封装
/*************NSObject+Swizzling.h******************/
#import <objc/runtime.h>
@interface NSObject (Swizzling)
+ (void)methodSwizzlingWithOriginalSelector:(SEL)originalSelector
bySwizzledSelector:(SEL)swizzledSelector;
@end
/*************NSObject+Swizzling.m******************/
#import "NSObject+Swizzling.h"
@implementation NSObject (Swizzling)
+ (void)methodSwizzlingWithOriginalSelector:(SEL)originalSelector bySwizzledSelector:(SEL)swizzledSelector{
Class class = [self class];
//原有方法
Method originalMethod = class_getInstanceMethod(class, originalSelector);
//替换原有方法的新方法
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
/**
先尝试給源SEL添加IMP,这里是为了避免源SEL没有实现IMP的情况.
class_addMethod会添加一个覆盖父类的实现,但不会取代原有类的实现。
也就是说如果class_addMethod返回YES,说明子类中没有方originalSelector,
通过class_addMethod为其添加了方法originalSelector,并使其实现(IMP)为我们想要替换的实现。
*/
BOOL didAddMethod = class_addMethod(class,originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {//添加成功:说明源SEL没有实现IMP,将源SEL的IMP替换到交换SEL的IMP
class_replaceMethod(class,swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {//添加失败:说明源SEL已经有IMP,直接将两个SEL的IMP交换即可
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
@end
分类可以添加@property的属性,但是仅仅是自动生成了get和set方法,并没有带下划线的属性和方法实现生成,但是runtime可以实现。
原理:给一个类声明属性,本质是给这个类添加关联,并不是直接把这个值的内存空间添加到类存空间。