標籤:設定 對比 release 需要 開發 文章 有用 method ble
你要知道的runtime都在這裡
轉載請註明出處 http://blog.csdn.net/u014205968/article/details/67639303
本文主要講解runtime相關知識,從原理到實踐,由於包含內容過多分為以下五篇文章詳細講解,可自行選擇需要瞭解的方向:
- 從runtime開始: 理解物件導向的類到面向過程的結構體
- 從runtime開始: 深入理解OC訊息轉寄機制
- 從runtime開始: 理解OC的屬性property
- 從runtime開始: 實踐Category添加屬性與黑魔法method swizzling
- 從runtime開始: 深入weak實現機理
本文是系列文章的第三篇文章從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","[email protected]\"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_getName和property_getAttributes方法擷取該屬性描述的name和attributes值,輸出的結果如下:
2017-03-27 09:59:20.914487 OCTest[2467:460742] cjmName T@"NSString",C,N,V_cjmName2017-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 = { "[email protected]\"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