关闭

Runtime的简单使用

标签: Runtime归档按钮绑定blockswift使用Runtime动态添加属性
587人阅读 评论(0) 收藏 举报
分类:

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 = 0
extension 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 = 0

typealias 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
查看评论

runtime介绍及基本使用

1. 概念         runtime(运行时系统),是一套基于C语言API,包含在 和中, 运行时系统的功能是在运行期间(而不是编译期或其他时机)通过代码去动态的操作类(获取类的内部信息和动态操作类的成员), 如创建一个新类、为某个类添加一个新的方法或者...
  • vbirdbest
  • vbirdbest
  • 2016-07-21 10:26
  • 940

runtime从入门到精通(六)—— runtime在实际开发中的应用

上一篇文章,我们学习了runtime的消息发送和消息转发机制(查看链接: runtime从入门到精通(五)—— 消息发送和消息转发 ),倒到此为止,有关runtime的理论知识介绍就先告于段落,小伙伴们,真正的干货来了,runtime在实际的开发中到底有何牛X的作用?我们该怎么使用这么牛X的工具呢?
  • coyote1994
  • coyote1994
  • 2016-09-08 12:08
  • 2186

iOS开发:runtime原理简单分析和基本使用场景

一:rumtime原理简单分析 runtime是运行时库(Runtime Library),也简称运行时。 它是一个主要是C和汇编写的库,对C进行了特殊的处理,将结构体视为对象,将函数视为方法,使得C有了面向对象的能力,从而才创造了Objective-C。 这点也可以看出,C是编译时语言,而OC是动...
  • indulgeIn
  • indulgeIn
  • 2016-04-10 12:25
  • 4132

runtime简单使用

一、runtime简介 RunTime简称运行时。OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制。对于C语言,函数的调用在编译的时候会决定调用哪个函数。对于OC的函数,属于动态调用过程,在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对...
  • yst19910702
  • yst19910702
  • 2017-02-20 14:37
  • 92

RunTime的运行机制简单使用

Runtime 自用笔记
  • shengyuCSDN
  • shengyuCSDN
  • 2016-08-09 08:50
  • 86

extjs的简单使用

ext下载地址:http://extjs.org.cn/node/515 当前下载的最新版本为ext-4.0.7-gpl.zip,解压之后文件目录结构如下图所示:   文件目录主要资源说明:   1、builds目录是ExtJS压缩后的代码,经过压缩的代码体积更小,加载更快...
  • weixin_41356040
  • weixin_41356040
  • 2018-01-22 10:25
  • 27

Mysql简单使用

1、查询表中某字段值,如查询学生表中姓名=hapasm select * from student where nam='hapasm' 2、查询物料表中,查询出所有物料代码重复的数据 select * from t_gd_material a where  (a....
  • hapasm
  • hapasm
  • 2016-12-22 21:03
  • 208

IOS runtime简单使用

一、runtime简介 RunTime简称运行时。OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制。 对于C语言,函数的调用在编译的时候会决定调用哪个函数。 对于OC的函数,属于动态调用过程,在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称...
  • MrLiangC
  • MrLiangC
  • 2016-09-13 17:55
  • 347

Runtime原理及简单使用

一、runtime简介 RunTime简称运行时。OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制。对于C语言,函数的调用在编译的时候会决定调用哪个函数。对于OC的函数,属于动态调用过程,在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对...
  • Vito_Jianxue
  • Vito_Jianxue
  • 2018-01-21 13:31
  • 35

iOS基础:UITableView简单使用

#pragma mark 实现此方法,就会出现Delete按钮 -(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPa...
  • gongwutianya
  • gongwutianya
  • 2016-07-28 21:20
  • 496
    个人资料
    • 访问:91292次
    • 积分:1551
    • 等级:
    • 排名:千里之外
    • 原创:61篇
    • 转载:4篇
    • 译文:1篇
    • 评论:20条
    最新评论