Runtime的简单使用

来源:互联网 发布:java代码生成jar包 编辑:程序博客网 时间:2024/05/20 23:38

Runtime的简单使用

       Runtime一直都是iOS开发者讨论的比较多的问题,如果不知道一点点Runtime的使用的话,感觉都不好意思说自己是一个用OC来开发Apple应用的开发人员。虽然Runtime使用的这类博客在网上可以说是烂大街了,但是我还是想记录一下自己对Runtime的学习情况。

在OC中使用Runtime需要导入#import <objc/objc-runtime.h>,而在Swift中则不需要,系统已经为我们导入了

一、消息发送

objc_msgSend(<#id self#>, <#SEL op, ...#>)
要使用这个方法,在Xcode7以上需要修改下设置信息:targets --> Build settings --> 搜索 msg  修改为 NO 即可索引出该方法
- (void)viewDidLoad {    [super viewDidLoad];    objc_msgSend(self, @selector(msgSend:param2:), @"param1", @"param2");}- (void)msgSend:(NSString *)param1 param2:(NSString *)param2{    NSLog(@"param1 = %@, param2 = %@",param1, param2);}
但是在swift中已经没有这个方法了

二、获取属性名、属性的值

获取成员属性名和值

- (NSDictionary *)getPropertyListAndValue{    NSMutableDictionary * dic = [NSMutableDictionary dictionary];        unsigned int count = 0;    Ivar * ivar = class_copyIvarList([self class], &count);        for (int i = 0; i < count; i ++) {        // 获取属性名字        const char * name = ivar_getName(ivar[i]);        NSString * propertyName = [NSString stringWithUTF8String:name];        // 获取属性值        NSString * value = [self valueForKey:propertyName];        [dic setObject:value forKey:propertyName];    }        free(ivar);    return dic;}

打印结果如下

2016-05-31 17:00:21.781 Runtime[4323:209497] array = {    "_IdCard" = 123;    "_age" = 12234;    "_name" = "\U5f20\U4e09";    "_sex" = 12;}
获取属性名和值
- (NSDictionary *)getPropertyListAndValue{    NSMutableDictionary * dic = [NSMutableDictionary dictionary];        unsigned int count = 0;    objc_property_t * property = class_copyPropertyList([self class], &count);        for (int i = 0; i < count; i ++) {        // 获取属性名字        const char * name = property_getName(property[i]);        NSString * propertyName = [NSString stringWithUTF8String:name];        // 获取属性值        NSString * value = [self valueForKey:propertyName];        [dic setObject:value forKey:propertyName];    }        free(property);    return dic;}
2016-05-31 17:04:51.762 Runtime[4357:213684] array = {    IdCard = 123;    age = 12234;    block = blnl;    name = "\U5f20\U4e09";    sex = 12;}
Swift中获取属性名和属性值
func getAllPropetyAndValue() -> [String: AnyObject] {        var count: UInt32 = 0        let ivar = class_copyIvarList(Persion.self, &count)        var dic: [String: AnyObject] = Dictionary()        for index in 0..<Int(count) {            // 获取属性名            let propety = ivar_getName(ivar[index])            let nameString = String.fromCString(propety)            // 获取值            let value = self.valueForKey(nameString!)            if let value = value {                dic[nameString!] = value            }        }        return dic    }
说明:class_copyPropertyList和property_getName都不能获取对应类父类的属性名,在OC中这两个方法获取的属性名存在一个"_"的差异,在Swift中则不存在

三、获取方法名
- (NSArray *)getMothodName{    NSMutableArray * mothodArray = [NSMutableArray array];        unsigned int count = 0;    Method * method = class_copyMethodList([self class], &count);    for (int i = 0; i < count; i ++) {        // 获取方法名字        SEL methodName = method_getName(method[i]);        const char * name = sel_getName(methodName);        [mothodArray addObject:[NSString stringWithUTF8String:name]];    }        return mothodArray;}
四、给OC的类目添加属性、把按钮的Action绑定Block

给OC的类目添加属性:

- (void)setParam:(NSString *)param{    objc_setAssociatedObject(self, @selector(param), param, OBJC_ASSOCIATION_COPY_NONATOMIC);}- (NSString *)param{    return objc_getAssociatedObject(self, _cmd);}
Swift中添加属性
private var addressKey: UInt8 = 0extension Persion {    var address: String? {        get {            return objc_getAssociatedObject(self, &addressKey) as? String        }        set {            if let newValue = newValue {                objc_setAssociatedObject(                    self,                    &addressKey,                    newValue as NSString?,objc_AssociationPolicy.OBJC_ASSOCIATION_COPY_NONATOMIC                )            }        }    }}
把按钮的Selector绑定Block:
typedef void(^ButtonBlock)();@interface UIButton (block)- (void)addTarget:(id)target events:(UIControlEvents)event block:(ButtonBlock)block;@end
const void * buttonKey = @"buttonKey";@implementation UIButton (block)- (void)addTarget:(id)target events:(UIControlEvents)event block:(ButtonBlock)block{    objc_setAssociatedObject(self, buttonKey, block, OBJC_ASSOCIATION_COPY_NONATOMIC);    [self addTarget:target action:@selector(processButton) forControlEvents:event];}- (void)processButton{    objc_getAssociatedObject(self, buttonKey);}@end
调用:
- (void)viewDidLoad{    [self.button addTarget:self events:UIControlEventTouchDown block:^{        NSLog(@"点击事件");    }];}

在swift中绑定:

private var ActionBlockKey: UInt8 = 0typealias ButtonBlock = ((sender: UIButton)-> Void)?class ActionBlockWrapper : NSObject {    var block : ButtonBlock    init(block: ButtonBlock) {        self.block = block    }}extension UIButton {    func addTarget(controlEvents: UIControlEvents, blick: ButtonBlock) {        objc_setAssociatedObject(self, &ActionBlockKey, ActionBlockWrapper.init(block: blick), objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)        addTarget(self, action: #selector(UIButton.processButton(_:)), forControlEvents: controlEvents)    }        func processButton(sender: UIButton) {        let wrapper = objc_getAssociatedObject(self, &ActionBlockKey) as! ActionBlockWrapper        wrapper.block!(sender: sender)    }}

四、方法交换

OC中的方法交换:

Method p1 = class_getInstanceMethod([Persion class], @selector(p1));Method p2 = class_getInstanceMethod([Persion class], @selector(p2));method_exchangeImplementations(p1, p2);[p p1];
swift中的方法交换: 
let p1: Method = class_getInstanceMethod(ViewController.self, #selector(ViewController.mothodFirst))let p2: Method = class_getInstanceMethod(ViewController.self, #selector(ViewController.mothodSecond))method_exchangeImplementations(p1, p2)mothodFirst()

五、解档、归档:当一个对象有很多属性需要进行解/归档的时候,不用一个个属性的去写解/归档操作

这里我定义了一个Persion类来说明

@interface Persion : NSObject@property (copy, nonatomic) NSString * name;@property (assign, nonatomic) int age;@property (copy, nonatomic) NSNumber * height;@end
实现:
- (void)encodeWithCoder:(NSCoder *)coder{    unsigned int count = 0;    Ivar * ivars = class_copyIvarList([Persion class], &count);        for (int i = 0; i < count; i++) {        Ivar ivar = ivars[i];        const char * name = ivar_getName(ivar);        NSString * strName = [NSString stringWithUTF8String:name];        // kvc 取值        id value = [self valueForKey:strName];        [coder encodeObject:value forKey:strName];    }    free(ivars);}- (instancetype)initWithCoder:(NSCoder *)coder{    self = [super init];    if (self) {        unsigned int count = 0;        // 获取类中所有成员变量名        Ivar * ivars = class_copyIvarList([Persion class], &count);        for (int i = 0; i < count; i++) {            Ivar ivar = ivars[i];            const char * name = ivar_getName(ivar);            NSString * strName = [NSString stringWithUTF8String:name];            // 进行减档            id value = [coder decodeObjectForKey:strName];            // 利用kvc对属性赋值            [self setValue:value forKey:strName];        }        free(ivars);    }    return self;}
这样是不是很方便了呢







0 0
原创粉丝点击