你要知道的runtime都在这里

转载请注明出处 http://blog.csdn.net/u014205968/article/details/67639303

本文主要解说runtime相关知识,从原理到实践。因为包括内容过多分为下面五篇文章具体解说,可自行选择须要了解的方向:

本文是系列文章的第三篇文章从runtime開始: 理解OC的属性property,主要从runtime出发解说属性property相关的底层实现和相关方法,因为之前的博客已经具体解说了property的底层实现,所以本文不再赘述,如有须要能够查看相关文章:iOS @property探究(一): 基础具体解释该文主要解说property的基础以及修饰符具体解释。iOS @property探究(二): 深入理解该文主要深入代码理解property的底层实现。因为与本文的内容由非常大的反复,因此本文不再赘述上述相关内容。

本文将会解说一些runtime操作属性的相关方法。

首先回想一下相关代码以及与property底层实现相关的两个结构体:

//OC自己定义类的定义
@interface Person : NSObject @property (nonatomic, copy) NSString* cjmName;
@property (nonatomic, assign) NSUInteger cjmAge; @end @implementation Person @synthesize cjmName = _cjmName;
@synthesize cjmAge = _cjmAge; @end //clang转写为.cpp的相关代码
struct _prop_t {
const char *name;
const char *attributes;
}; static struct /*_prop_list_t*/ {
unsigned int entsize; // sizeof(struct _prop_t)
unsigned int count_of_properties;
struct _prop_t prop_list[2];
} _OBJC_$_PROP_LIST_Person __attribute__ ((used, section ("__DATA,__objc_const"))) = {
sizeof(_prop_t),
2,
{{"cjmName","T@\"NSString\",C,N,V_cjmName"},
{"cjmAge","TQ,N,V_cjmAge"}}
};

通过上述代码事实上我们能够看出,一个@property属性在底层就是一个结构体描写叙述,那么我们怎样获取这个结构体呢?能够通过例如以下代码获取:

int main(int argc, const char * argv[]) {
@autoreleasepool {
Person* p = [[Person alloc] init];
p.cjmName = @"Jiaming Chen"; unsigned int propertyCount = 0;
objc_property_t *propertyList = class_copyPropertyList([p class], &propertyCount);
for (int i = 0; i < propertyCount; i++) {
const char* name = property_getName(propertyList[i]);
const char* attributes = property_getAttributes(propertyList[i]);
NSLog(@"%s %s", name, attributes);
}
}
return 0;
}

首先看一下objc_property_t是什么。在objc/runtime.h中能够找到相关定义:

typedef struct objc_property *objc_property_t;

它是一个指向结构体struct objc_property的指针,这里的结构体struct objc_property事实上就是前文中.cpp文件里的struct _prop_t结构体,通过class_copyPropertyList方法就能够获取到相关类的全部属性。具体函数声明例如以下:

/**
* Describes the properties declared by a class.
*
* @param cls The class you want to inspect.
* @param outCount On return, contains the length of the returned array.
* If \e outCount is \c NULL, the length is not returned.
*
* @return An array of pointers of type \c objc_property_t describing the properties
* declared by the class. Any properties declared by superclasses are not included.
* The array contains \c *outCount pointers followed by a \c NULL terminator. You must free the array with \c free().
*
* If \e cls declares no properties, or \e cls is \c Nil, returns \c NULL and \c *outCount is \c 0.
*/
OBJC_EXPORT objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);

通过凝视能够看出。第一个參数是相关类的类对象(如有疑问能够查阅本系列文章的前两篇文章)。第二个參数是一个指向unsigned int的指针。用于指明property的数量,通过该方法就能够获取到全部的属性,接下来能够通过property_getNameproperty_getAttributes方法获取该属性描写叙述的nameattributes值,输出的结果例如以下:

2017-03-27 09:59:20.914487 OCTest[2467:460742] cjmName T@"NSString",C,N,V_cjmName
2017-03-27 09:59:20.915321 OCTest[2467:460742] cjmAge TQ,N,V_cjmAge

name非常好理解。后面的attributes通过对照不难发现其规律,感兴趣的读者也能够多设置几个不同类型、不同修饰符的property看一下输出。

除此之外哈有一下几个方法用于依据属性名获取一个属性描写叙述结构体、加入属性、替换属性等方法。

/**
* Returns a property with a given name of a given class.
*
* @param cls The class you want to inspect.
* @param name The name of the property you want to inspect.
*
* @return A pointer of type \c objc_property_t describing the property, or
* \c NULL if the class does not declare a property with that name,
* or \c NULL if \e cls is \c Nil.
*/
OBJC_EXPORT objc_property_t class_getProperty(Class cls, const char *name)
OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0); /**
* Adds a property to a class.
*
* @param cls The class to modify.
* @param name The name of the property.
* @param attributes An array of property attributes.
* @param attributeCount The number of attributes in \e attributes.
*
* @return \c YES if the property was added successfully, otherwise \c NO
* (for example, the class already has that property).
*/
OBJC_EXPORT BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0); /**
* Replace a property of a class.
*
* @param cls The class to modify.
* @param name The name of the property.
* @param attributes An array of property attributes.
* @param attributeCount The number of attributes in \e attributes.
*/
OBJC_EXPORT void class_replaceProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
OBJC_AVAILABLE(10.7, 4.3, 9.0, 1.0);

举个简单的栗子:

int main(int argc, const char * argv[]) {
@autoreleasepool {
Person* p = [[Person alloc] init];
p.cjmAge = 20;
p.cjmName = @"Jiaming Chen"; unsigned int propertyCount = 0;
objc_property_t *propertyList = class_copyPropertyList([p class], &propertyCount);
for (int i = 0; i < propertyCount; i++) {
const char* name = property_getName(propertyList[i]);
const char* attributes = property_getAttributes(propertyList[i]);
NSLog(@"%s %s", name, attributes);
}
objc_property_attribute_t attributes = {
"T@\"NSString\",C,N,V_studentIdentifier",
"",
};
class_addProperty([p class], "studentIdentifier", &attributes, 1);
objc_property_t property = class_getProperty([p class], "studentIdentifier");
NSLog(@"%s %s", property_getName(property), property_getAttributes(property));
}
return 0;
}

通过上述方法就能加入一个属性,因为本人水平有限实际开发中没实用过上述方法。具体实际样例也举不出来所以不再过多赘述。

备注

因为作者水平有限,难免出现纰漏,如有问题还请指教。

iOS runtime探究(三): 从runtime開始理解OC的属性property的更多相关文章

  1. iOS runtime探究(二): 从runtime開始深入理解OC消息转发机制

    你要知道的runtime都在这里 转载请注明出处 http://blog.csdn.net/u014205968/article/details/67639289 本文主要解说runtime相关知识, ...

  2. (转发)IOS高级开发~Runtime(三)

    11.系统类的方法实现部分替换 - (void) methodExchange { Method m1 = class_getInstanceMethod([NSStringclass],@selec ...

  3. 李洪强iOS经典面试题156 - Runtime详解(面试必备)

    李洪强iOS经典面试题156 - Runtime详解(面试必备)   一.runtime简介 RunTime简称运行时.OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制. 对于C ...

  4. iOS模式详解—「runtime面试、工作」看我就 🐒 了 ^_^.

    Write in the first[写在最前] 对于从事 iOS 开发人员来说,当提到 ** runtime时,我想都可以说出来 「runtime 运行时」和基本使用的方法.相信很多开发者跟我当初一 ...

  5. iOS 模式详解—「runtime面试、工作」看我就 🐒 了 ^_^.

    引导 Copyright © PBwaterln Unauthorized shall not be *copy reprinted* . 对于从事 iOS 开发人员来说,所有的人都会答出「runti ...

  6. 从零開始学android&lt;数据存储(1)SharedPreferences属性文件.三十五.&gt;

    在android中有五种保存数据的方法.各自是: Shared Preferences Store private primitive data in key-value pairs. 相应属性的键值 ...

  7. iOS中从零開始使用protobuf

    让我们一起打开以下这个链接 https://github.com/alexeyxo/protobuf-objc 在github上有protobuf-objc,当中的readme能够教会我们安装prot ...

  8. 今天開始慢下脚步,開始ios技术知识的查漏补缺。

    从2014.6.30 開始工作算起. 如今已经是第416天了.不止不觉.时间过的真快. 通过对之前工作的总结.发现,你的知识面.会决定你面对问题时的态度.过程和结果. 简单来讲.知识面拓展了,你才干有 ...

  9. iOS开发黑科技之runtime

    iOS 开发之黑科技-runtime runtime其实就是oc底层的一套C语音的API 调用方法的本质就是发消息, 1.动态交换两个方法的实现(特别是交换系统自动的方法) 2.动态添加对象的成员变量 ...

随机推荐

  1. Graph database_neo4j 底层存储结构分析(2)

    3       neo4j存储结构 neo4j 中,主要有4类节点,属性,关系等文件是以数组作为核心存储结构:同时对节点,属性,关系等类型的每个数据项都会分配一个唯一的ID,在存储时以该ID 为数组的 ...

  2. 使用 IntraWeb (1) - 先测试如何部署为 Asp.Net 的应用

    IntraWeb 14 可以部署为 Asp.Net 的应用程序, 需要 NET Framework 4.5 和 ASP.NET MVC 4 或之上版本的支持; 这下, 只能用虚拟主机的朋友有福了! 我 ...

  3. 通过WinAPI播放PCM声音

    在Windows平台上,播放PCM声音使用的API通常有如下两种. waveOut and waveIn:传统的音频MMEAPI,也是使用的最多的 xAudio2:C++/COM API,主要针对游戏 ...

  4. How to add Leading Zeroes to a Number (Delphi Format)

    How to add Leading Zeroes to a Number (Delphi Format) Here's how convert (an integer) number to a st ...

  5. Go语言中查询SqlServer数据库

    一.Go语言中查询MsSQL数据库: // main.go package main import ( "database/sql" "fmt" "l ...

  6. Revit API创建标高,单位转换

    一业内朋友让我写个快速创建标高的插件. ;             ; i <= iNum; i++)             {                 Level level = d ...

  7. ES6的一些基本用法

    ● let ● variable hoisting ● arrow Function, Lambda表达式 ● Destructuring Assignments 解构赋值 ● 默认参数值 Defau ...

  8. Linux source命令(转)

    Linux source命令: 通常用法:source filepath 或 . filepath 功能:使当前shell读入路径为filepath的shell文件并依次执行文件中的所有语句,通常用于 ...

  9. springboot—spring aop 实现系统操作日志记录存储到数据库

    原文:https://www.jianshu.com/p/d0bbdf1974bd 采用方案: 使用spring 的 aop 技术切到自定义注解上,针对不同注解标志进行参数解析,记录日志 缺点是要针对 ...

  10. eval json ajax

    在JS中将JSON的字符串解析成JSON数据格式,一般有两种方式: 1.一种为使用eval()函数. 2. 使用Function对象来进行返回解析. 使用eval函数来解析,并且使用jquery的ea ...