自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

iOS runtime實戰(zhàn)應用:成員變量和屬性

移動開發(fā)
有筒子在面試的時候,遇到這樣一個問題:“你知道成員變量的本質(zhì)是什么嗎?”,筒子立馬懵逼了,成員變量的本質(zhì)?成員變量就是成員變量啊,平時只管用,還有什么更深層的含義?本文著重介紹runtime中成員變量和屬性的定義和使用

[[164431]]

原文

前言

在開始之前建議先閱讀iOS runtime的基礎理解篇:iOS內(nèi)功篇:runtime

有筒子在面試的時候,遇到這樣一個問題:“你知道成員變量的本質(zhì)是什么嗎?”,筒子立馬懵逼了,成員變量的本質(zhì)?成員變量就是成員變量啊,平時只管用,還有什么更深層的含義?本文著重介紹runtime中成員變量和屬性的定義和使用。

名詞解析

成員變量

1、定義:

Ivar: 實例變量類型,是一個指向objc_ivar結構體的指針

  1. typedef struct objc_ivar *Ivar; 

2、操作函數(shù):

  1. // 獲取所有成員變量 
  2. class_copyIvarList 
  1. // 獲取成員變量名 
  2. ivar_getName 
  1. // 獲取指定名稱的成員變量 
  2. class_getInstanceVariable 
  1. // 獲取成員變量類型編碼 
  2. ivar_getTypeEncoding 
  1. // 設置某個對象成員變量的值 
  2. object_setIvar 
  1. // 獲取某個對象成員變量的值 
  2. object_getIvar 

3、使用實例:

Model的頭文件聲明如下:

  1. @interface Model : NSObject { 
  2.         NSString * _str1; 
  3.     } 
  4.     @property NSString * str2; 
  5.     @property (nonatomic, copy) NSDictionary * dict1; 
  6.     @end 

獲取其成員變量:

  1. unsigned int outCount = 0
  2. Ivar * ivars = class_copyIvarList([Model class], &outCount); 
  3. for (unsigned int i = 0; i < outCount; i ++) { 
  4.    Ivar ivar = ivars[i]; 
  5.    const char * name = ivar_getName(ivar); 
  6.    const char * type = ivar_getTypeEncoding(ivar); 
  7.    NSLog(@"類型為 %s 的 %s ",type, name); 
  8. free(ivars); 

打印結果:

  1. runtimeIvar[602:16885] 類型為 @"NSString" 的 _str1  
  2. runtimeIvar[602:16885] 類型為 @"NSString" 的 _str2  
  3. runtimeIvar[602:16885] 類型為 @"NSDictionary" 的 _dict1 

屬性

1、定義:

objc_property_t:聲明的屬性的類型,是一個指向objc_property結構體的指針

  1. typedef struct objc_property *objc_property_t; 

2、操作函數(shù):

  1. // 獲取所有屬性 
  2. class_copyPropertyList 

說明:使用class_copyPropertyList并不會獲取無@property聲明的成員變量

  1. // 獲取屬性特性描述字符串 
  2. property_getAttributes 
  1. // 獲取屬性名 
  2. property_getName 
  1. // 獲取所有屬性特性 
  2. property_copyAttributeList 

說明:

property_getAttributes函數(shù)返回objc_property_attribute_t結構體列表,objc_property_attribute_t結構體包含name和value,常用的屬性如下:

  1. 屬性類型  name值:T  value:變化 
  2. 編碼類型  name值:C(copy) &(strong) W(weak) 空(assign) 等 value:無 
  3. 非/原子性 name值:空(atomic) N(Nonatomic)  value:無 
  4. 變量名稱  name值:V  value:變化 

使用property_getAttributes獲得的描述是property_copyAttributeList能獲取到的所有的name和value的總體描述,如 T@"NSDictionary",C,N,V_dict1

3、使用實例:

  1. unsigned int outCount = 0
  2.     objc_property_t * properties = class_copyPropertyList([Model class], &outCount); 
  3.     for (unsigned int i = 0; i < outCount; i ++) { 
  4.         objc_property_t property = properties[i]; 
  5.         //屬性名 
  6.         const char * name = property_getName(property); 
  7.         //屬性描述 
  8.         const char * propertyAttr = property_getAttributes(property); 
  9.         NSLog(@"屬性描述為 %s 的 %s ", propertyAttr, name); 
  10.           
  11.         //屬性的特性 
  12.         unsigned int attrCount = 0
  13.         objc_property_attribute_t * attrs = property_copyAttributeList(property, &attrCount); 
  14.         for (unsigned int j = 0; j < attrCount; j ++) { 
  15.             objc_property_attribute_t attr = attrs[j]; 
  16.             const char * name = attr.name; 
  17.             const char * value = attr.value; 
  18.             NSLog(@"屬性的描述:%s 值:%s", name, value); 
  19.         } 
  20.         free(attrs); 
  21.         NSLog(@"\n"); 
  22.     } 
  23.     free(properties); 

打印結果:

  1. runtimeIvar[661:27041] 屬性描述為 T@"NSString",&,V_str2 的 str2  
  2. runtimeIvar[661:27041] 屬性的描述:T 值:@"NSString" 
  3. runtimeIvar[661:27041] 屬性的描述:& 值: 
  4. runtimeIvar[661:27041] 屬性的描述:V 值:_str2 
  5. runtimeIvar[661:27041]  
  6. runtimeIvar[661:27041] 屬性描述為 T@"NSDictionary",C,N,V_dict1 的 dict1  
  7. runtimeIvar[661:27041] 屬性的描述:T 值:@"NSDictionary" 
  8. runtimeIvar[661:27041] 屬性的描述:C 值: 
  9. runtimeIvar[661:27041] 屬性的描述:N 值: 
  10. runtimeIvar[661:27041] 屬性的描述:V 值:_dict1 
  11. runtimeIvar[661:27041

應用實例

1、Json到Model的轉化

在開發(fā)中相信最常用的就是接口數(shù)據(jù)需要轉化成Model了(當然如果你是直接從Dict取值的話。。。),很多開發(fā)者也都使用著名的第三方庫如JsonModel、Mantle或MJExtension等,如果只用而不知其所以然,那真和“搬磚”沒啥區(qū)別了,下面我們使用runtime去解析json來給Model賦值。

原理描述:用runtime提供的函數(shù)遍歷Model自身所有屬性,如果屬性在json中有對應的值,則將其賦值。

核心方法:在NSObject的分類中添加方法:

  1. - (instancetype)initWithDict:(NSDictionary *)dict { 
  2.   
  3.     if (self = [self init]) { 
  4.         //(1)獲取類的屬性及屬性對應的類型 
  5.         NSMutableArray * keys = [NSMutableArray array]; 
  6.         NSMutableArray * attributes = [NSMutableArray array]; 
  7.         /* 
  8.          * 例子 
  9.          * name = value3 attribute = T@"NSString",C,N,V_value3 
  10.          * name = value4 attribute = T^i,N,V_value4 
  11.          */ 
  12.         unsigned int outCount; 
  13.         objc_property_t * properties = class_copyPropertyList([self class], &outCount); 
  14.         for (int i = 0; i < outCount; i ++) { 
  15.             objc_property_t property = properties[i]; 
  16.             //通過property_getName函數(shù)獲得屬性的名字 
  17.             NSString * propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding]; 
  18.             [keys addObject:propertyName]; 
  19.             //通過property_getAttributes函數(shù)可以獲得屬性的名字和@encode編碼 
  20.             NSString * propertyAttribute = [NSString stringWithCString:property_getAttributes(property) encoding:NSUTF8StringEncoding]; 
  21.             [attributes addObject:propertyAttribute]; 
  22.         } 
  23.         //立即釋放properties指向的內(nèi)存 
  24.         free(properties); 
  25.   
  26.         //(2)根據(jù)類型給屬性賦值 
  27.         for (NSString * key in keys) { 
  28.             if ([dict valueForKey:key] == nil) continue
  29.             [self setValue:[dict valueForKey:key] forKey:key]; 
  30.         } 
  31.     } 
  32.     return self; 
  33.   

讀者可以進一步思考:

  • 如何識別基本數(shù)據(jù)類型的屬性并處理

  • 空(nil,null)值的處理

  • json中嵌套json(Dict或Array)的處理

嘗試解決以上問題,你也能寫出屬于自己的功能完備的Json轉Model庫。

2、快速歸檔

有時候我們要對一些信息進行歸檔,如用戶信息類UserInfo,這將需要重寫initWithCoder和encodeWithCoder方法,并對每個屬性進行encode和decode操作。那么問題來了:當屬性只有幾個的時候可以輕松寫完,如果有幾十個屬性呢?那不得寫到天荒地老?。。。

原理描述:用runtime提供的函數(shù)遍歷Model自身所有屬性,并對屬性進行encode和decode操作。

核心方法:在Model的基類中重寫方法:

  1. - (id)initWithCoder:(NSCoder *)aDecoder { 
  2.     if (self = [super init]) { 
  3.         unsigned int outCount; 
  4.         Ivar * ivars = class_copyIvarList([self class], &outCount); 
  5.         for (int i = 0; i < outCount; i ++) { 
  6.             Ivar ivar = ivars[i]; 
  7.             NSString * key = [NSString stringWithUTF8String:ivar_getName(ivar)]; 
  8.             [self setValue:[aDecoder decodeObjectForKey:key] forKey:key]; 
  9.         } 
  10.     } 
  11.     return self; 
  12.   
  13. - (void)encodeWithCoder:(NSCoder *)aCoder { 
  14.     unsigned int outCount; 
  15.     Ivar * ivars = class_copyIvarList([self class], &outCount); 
  16.     for (int i = 0; i < outCount; i ++) { 
  17.         Ivar ivar = ivars[i]; 
  18.         NSString * key = [NSString stringWithUTF8String:ivar_getName(ivar)]; 
  19.         [aCoder encodeObject:[self valueForKey:key] forKey:key]; 
  20.     } 

3、訪問私有變量

我們知道,OC中沒有真正意義上的私有變量和方法,要讓成員變量私有,要放在m文件中聲明,不對外暴露。如果我們知道這個成員變量的名稱,可以通過runtime獲取成員變量,再通過getIvar來獲取它的值。

方法:

  1. Ivar ivar = class_getInstanceVariable([Model class], "_str1"); 
  2. NSString * str1 = object_getIvar(model, ivar); 

歡迎大家交流探討。

責任編輯:倪明 來源: 明仔Su的簡書
相關推薦

2012-04-09 13:43:12

Java

2012-05-14 17:06:46

iOS

2014-04-01 10:50:42

iOS開發(fā)runtimeObjective-C

2015-08-07 09:33:24

RuntimeModel

2010-03-17 16:54:10

Java sum傳遞

2020-06-19 09:15:11

Python內(nèi)置方法屬性應用

2011-08-02 18:30:32

iOS 應用程序 屬性

2013-12-26 09:27:51

AndroidiOS調(diào)查數(shù)據(jù)

2011-09-16 17:12:01

iOS應用Android應用Ribblet

2018-08-09 20:47:41

2021-04-20 08:31:59

應用監(jiān)控高可用

2011-09-19 10:24:58

蘋果iOS谷歌

2017-04-11 08:36:09

iOS編譯應用

2014-03-07 09:41:20

AndroidiOS惡意應用

2010-08-31 15:24:43

CSSpositionabsolute

2010-01-18 14:54:00

VB.NET共享成員變

2009-11-12 11:18:28

VS Ribbon界面

2024-12-30 11:12:59

C++靜態(tài)成員函數(shù)

2018-11-07 09:39:03

Runtime開發(fā)項目

2010-08-19 13:43:07

marginpadding
點贊
收藏

51CTO技術棧公眾號