Objective-C Runtime Classes
objective-c语言的许多决策可以在编译和运行时执行。只要有可能,它是动态的。这意味着objective-c语言不仅需要一个编译器,还需要一个运行时来执行编译的代码。runtime系统是一种用于objective-c语言的操作系统,它使oc语言工作起来。
runtime的核心是在运行时动态操作类和消息分发给其他对象,本文档主要介绍在运行时动态操作类。
你可以从中学到运行时动态操作类。但是,多数情况下,我们并不需要编写runtime系统的相关代码。
注意:在runtime中,所有的char * 数据是utf-8编码。
一、准备工作
1. 导入框架objc/runtime.h
#import < objc/runtime.h >
2. user类
user.h
// // user.h // runtime // // created by yangjun on 15/9/21. // copyright © 2015年 六月. all rights reserved. // #import /// 用户 @interface user : nsobject @property (nonatomic, copy) nsstring *username;///< 用户名 /** * 初始化 * * @param username 用户名 * * @return id */ - (id)initwithusername:(nsstring *)username; /** * 初始化 * * @param username 用户名 * * @return id */ + (id)userwithusername:(nsstring *)username; @end
user.m
// // user.m // runtime // // created by yangjun on 15/9/21. // copyright © 2015年 六月. all rights reserved. // #import user.h @implementation user + (id)userwithusername:(nsstring *)username { user *user = [[user alloc] init]; user.username = username; return username; } #pragma mark 初始化 - (id)initwithusername:(nsstring *)username { self = [super init]; if (self) { self.username = username; } return self; } @end
二、类
1.源代码
#pragma mark - 类 - (void)testclass { // 获取类 id userclass = objc_getclass(user); nslog(@%@, userclass); // 等价 userclass = [user class]; nslog(@%@, userclass); // 父类 fprintf(stdout, 父类 ); id superuserclass = class_getsuperclass(userclass); nslog(@%@, superuserclass); // 等价 superuserclass = [user new].superclass; nslog(@%@, superuserclass); // 更改对象的类 fprintf(stdout, 更改对象的类 ); user *user = [user new]; nslog(@类:%@ username:%@, user, user.username); userclass = object_setclass(user, [classtest class]);// 类替换,并返回原来的类属性 nslog(@类:%@ username:%@, user, user.username); }
2.输出
2015-09-23 10:12:52.140 runtime[14129:681188] user
2015-09-23 10:12:52.141 runtime[14129:681188] user
父类
2015-09-23 10:12:52.141 runtime[14129:681188] nsobject
2015-09-23 10:12:52.141 runtime[14129:681188] nsobject
更改对象的类
2015-09-23 10:12:52.141 runtime[14129:681188] 类: username:(null)
2015-09-23 10:12:52.141 runtime[14129:681188] 类: username:阳君
三、类名
1.源代码
#pragma mark - 类名 - (void)testname{ // 获取class id userclass = objc_getclass(user); const char *classname = class_getname(userclass); fprintf(stdout, 类名:%s , classname); // 等价 classname = object_getclassname(userclass); fprintf(stdout, 类名:%s , classname); // 等价oc userclass = [user class]; nsstring *name = nsstringfromclass(userclass); nslog(@类名:%@, name); // 底层转换 name = [nsstring stringwithcstring:classname encoding:nsutf8stringencoding]; nslog(@类名:%@, name); }
2.输出
类名:user
类名:user
2015-09-23 10:14:03.278 runtime[14140:681770] 类名:user
2015-09-23 10:14:03.279 runtime[14140:681770] 类名:user
四、属性
1.源代码
#pragma mark - 属性 - (void)testpropertyname { // 获取所有属性 fprintf(stdout, 获取所有属性 ); id userclass = objc_getclass(user); unsigned int outcount, i; objc_property_t *properties = class_copypropertylist(userclass, &outcount);// 所有属性 for (i = 0; i < outcount; i++) { objc_property_t property = properties[i];// 属性 const char *propertyname = property_getname(property);// 属性名 const char *propertyattributes = property_getattributes(property); //属性类型 fprintf(stdout, %s %s , propertyname, propertyattributes); // 等价输出 nslog(@%@, [nsstring stringwithcstring:propertyname encoding:nsutf8stringencoding]); } // 单一属性 fprintf(stdout, 单一属性 ); ivar var = class_getinstancevariable(userclass, _username); const char *typeencoding =ivar_gettypeencoding(var); const char *ivarname = ivar_getname(var); fprintf(stdout, 属性名:%s; 类型:%s , ivarname, typeencoding); // 设置/获取属性值,需要关闭arc模式 fprintf(stdout, 设置/获取属性值 ); user *user = [[[user alloc] init] autorelease]; nsstring *username = @阳君; object_setinstancevariable(user, _username, username); nslog(@user.username:%@, user.username); user.username = @开启arc;// 修改值 object_getinstancevariable(user, _username, (void*)&username); nslog(@user.username:%@, username); }
2.输出
获取所有属性
username t@”nsstring”,c,n,v_username
2015-09-23 10:18:54.365 runtime[14155:684097] username
单一属性
属性名:_username; 类型:@”nsstring”
设置/获取属性值
2015-09-23 10:18:54.366 runtime[14155:684097] user.username:阳君
2015-09-23 10:18:54.367 runtime[14155:684097] user.username:开启arc
五、方法
1.源代码
全局方法:
nsstring *classaddmethodimp(id self, sel _cmd, nsstring *str) { // implementation .... nslog(@值:%@, str); return str; } nsstring *username(id self, sel _cmd) { return @oc; }
局部方法:
#pragma mark - 方法 - (void)testmethod { // 获取所有方法 fprintf(stdout, 获取所有方法 ); id userclass = objc_getclass(user); u_int count;// unsigned int method *methods= class_copymethodlist(userclass, &count);// 所有方法,只包含实例方法) for (int i = 0; i < count ; i++) { method method = methods[i]; sel name = method_getname(method);// 转为方法 const char *selname = sel_getname(name);// 转为方法名 const char *methodtypeencoding = method_gettypeencoding(method);// 方法传输的参数 char *methodtype = method_copyreturntype(method);// 方法返回的类型 fprintf(stdout, 方法名:%s; 返回类型%s; 参数:%s , selname, methodtype, methodtypeencoding); } // 1.提取method(类方法) fprintf(stdout, 方法提取 ); sel name = sel_registername(userwithusername:); method method = class_getclassmethod(userclass, name); name = method_getname(method); fprintf(stdout, 提取方法(+):%s , sel_getname(name)); // 2.提取method(实例方法) name = sel_registername(initwithusername:); method = class_getinstancemethod(userclass, name); name = method_getname(method); fprintf(stdout, 提取方法(-):%s , sel_getname(name)); // 3.提取imp imp imp = method_getimplementation(method); // 只能获取(-)方法 imp = class_getmethodimplementation(userclass, name); imp = class_getmethodimplementation_stret(userclass, name); // 等价 user *user = [[user alloc] init]; imp = [user methodforselector:name]; // 类增加方法(全局方法) fprintf(stdout, 类增加方法 ); name = sel_registername(classaddmethodimp); bool addmethod = class_addmethod(userclass, name, (imp)classaddmethodimp,i@:@); // 判断类是否有此方法 if (addmethod && class_respondstoselector(userclass, name) && [user respondstoselector:name]) { fprintf(stdout, 类%s添加方法%s成功 , class_getname(userclass), sel_getname(name)); } // 类添加方法(-) name = @selector(classaddmethod:); method = class_getinstancemethod(self.class, name);// 方法体 imp = method_getimplementation(method);// 方法的实现 class_addmethod(userclass, name, imp, v@:); // 方法调用 id methodback = [user performselector:@selector(classaddmethod:) withobject:@阳君]; nslog(@类%@调用方法%@ 返回:%@, nsstringfromclass(user.class), [nsstring stringwithcstring:sel_getname(name) encoding:nsutf8stringencoding], methodback); // 方法交换 fprintf(stdout, 方法交换 ); method m1 = class_getinstancemethod([self class], @selector(username)); method m2 = class_getinstancemethod([self class], @selector(username2)); method_exchangeimplementations(m1, m2); nslog(@%@, [self username]); nslog(@%@, [self username2]); // 方法替换 fprintf(stdout, 方法替换 ); method usernamemethod = class_getinstancemethod(self.class, @selector(username)); imp usernameimp = method_getimplementation(usernamemethod); method setusernamemethod = class_getinstancemethod(self.class, @selector(username2)); method_setimplementation(setusernamemethod, usernameimp); nslog(@%@, [self username]); nslog(@%@, [self username2]); // 方法覆盖,只能使用全局方法替换,方法名需要一致 fprintf(stdout, 方法覆盖 ); nslog(@%@, user.username); name = sel_registername(username); imp = class_replacemethod(userclass, name, (imp)username,i@:@); nslog(@%@, user.username); } #pragma mark 覆盖的方法 - (nsstring *)username { return @阳君; } - (nsstring *)username2 { return @ios; } #pragma mark 增加的方法 - (nsstring *)classaddmethod:(nsstring *)str { return str; }
2.输出
获取所有方法
方法名:initwithusername:; 返回类型@; 参数:@24@0:8@16
方法名:username; 返回类型@; 参数:@16@0:8
方法名:setusername:; 返回类型v; 参数:v24@0:8@16
方法提取
提取方法(+):userwithusername:
提取方法(-):initwithusername:
类增加方法
类user添加方法classaddmethodimp成功
2015-09-23 10:21:19.167 runtime[14182:685354] 类user调用方法classaddmethod: 返回:阳君
方法交换
2015-09-23 10:21:19.168 runtime[14182:685354] ios
2015-09-23 10:21:19.168 runtime[14182:685354] 阳君
方法替换
2015-09-23 10:21:19.168 runtime[14182:685354] ios
2015-09-23 10:21:19.168 runtime[14182:685354] ios
方法覆盖
2015-09-23 10:21:19.169 runtime[14182:685354] (null)
2015-09-23 10:21:19.169 runtime[14182:685354] oc
推荐阅读
-
浅析Objective-C中分类Category的使用
-
iOS开发- runtime基本用法解析和用runtime给键盘添加工具栏和按钮响应事件
-
Objective-c调用Swift
-
Objective-C 获取NSDate对象的年月日时分秒 && NSCalender的使用
-
Swift 与Objective-c语法参照
-
MindManager 15中文版怎么解决runtime error?
-
Win10中开机出现Runtime Error错误怎么办?
-
【iOS异常】 JSonKit does not support Objective-C Automatic Reference Counting(ARC)
-
Objective-C中字符串的拼接方法小结
-
Resource Path Location Type Target runtime Apache Tomcat v6.0 is not defined(项目报错)已解决