运行时相关
1.獲取或者設置實例變量的值
??? FirstModel * model=[[FirstModel alloc]init];
??? model.name=@"xiaoming";
??? const char *pConstChar??????????? = [@"_name" UTF8String];
??? Ivar ivar=class_getInstanceVariable([model class], pConstChar);//獲取類指定變量(用于下面兩個函數)
??? object_setIvar(model, ivar, @"liming");//設置實例變量的值
??? NSLog(@"%@",object_getIvar(model, ivar));//獲取實例指定變量的值
??? 注意點:屬性的值應該是oc對象,而不是簡單數據類型,不然程序要崩潰
?
?
?對比kvc:
???? KVC的操作方法由NSKeyValueCoding協議提供,而NSObject就實現了這個協議,也就是說ObjC中幾乎所有的對象都支持KVC操作,常用的KVC操作方法如下:
- 動態設置: setValue:屬性值 forKey:屬性名(用于簡單路徑)、setValue:屬性值 forKeyPath:屬性路徑(例如Person有一個Account類型的屬性,account實例有balance屬性,[person1 setValue:@100000000.0 forKeyPath:@"account.balance"];)
- 動態讀取: valueForKey:屬性名 、valueForKeyPath:屬性名(用于復合路徑)
???? KVC如何查找一個屬性進行讀取呢?具體查找規則(假設現在要利用KVC對a進行讀取):
- 如果是動態設置屬性,則優先考慮調用setA方法,如果沒有該方法則優先考慮搜索成員變量_a,如果仍然不存在則搜索成員變量a,如果最后仍然沒 搜索到則會調用這個類的setValue:forUndefinedKey:方法(注意搜索過程中不管這些方法、成員變量是私有的還是公共的都能正確設 置);
- 如果是動態讀取屬性,則優先考慮調用a方法(屬性a的getter方法),如果沒有搜索到則會優先搜索成員變量_a,如果仍然不存在則 搜索成員變量a,如果最后仍然沒搜索到則會調用這個類的valueforUndefinedKey:方法(注意搜索過程中不管這些方法、成員變量是私有的 還是公共的都能正確讀取);
- 即使是一個私有變量也可以使用kvc進行訪問;
?
?
首先我們來看看obj這個對象,iOS中的obj都繼承于NSObject。
@interface NSObject <nsobject> {Class isa OBJC_ISA_AVAILABILITY; }</nsobject> 在NSObjcet中存在一個Class的isa指針。然后我們看看Class: typedef struct objc_class *Class; struct objc_class {Class isa; // 指向metaclassClass super_class ; // 指向其父類const char *name ; // 類名long version ; // 類的版本信息,初始化默認為0,可以通過runtime函數class_setVersion和class_getVersion進行修改、讀取long info; // 一些標識信息,如CLS_CLASS (0x1L) 表示該類為普通 class ,其中包含對象方法和成員變量;CLS_META (0x2L) 表示該類為 metaclass,其中包含類方法;long instance_size ; // 該類的實例變量大小(包括從父類繼承下來的實例變量);struct objc_ivar_list *ivars; // 用于存儲每個成員變量的地址struct objc_method_list **methodLists ; // 與 info 的一些標志位有關,如CLS_CLASS (0x1L),則存儲對象方法,如CLS_META (0x2L),則存儲類方法;struct objc_cache *cache; // 指向最近使用的方法的指針,用于提升效率;struct objc_protocol_list *protocols; // 存儲該類遵守的協議 }注意:所有metaclass中isa指針都指向跟metaclass。而跟metaclass則指向自身。Root metaclass是通過繼承Root class產生的。與root class結構體成員一致,也就是前面提到的結構。不同的是Root metaclass的isa指針指向自身。
Class類中其他的成員這里就先不做過多解釋了,下面我們來看看:
@selector (makeText):這是一個SEL方法選擇器。SEL其主要作用是快速的通過方法名字(makeText)查找到對應方法的函數指針,然后調用其函 數。SEL其本身是一個Int類型的一個地址,地址中存放著方法的名字。對于一個類中。每一個方法對應著一個SEL。所以iOS類中不能存在2個名稱相同 的方法,即使參數類型不同,因為SEL是根據方法名字生成的,相同的方法名稱只能對應一個SEL。
下面我們就來看看具體消息發送之后是怎么來動態查找對應的方法的。
首先,編譯器將代碼[obj makeText];轉化為objc_msgSend(obj, @selector (makeText));,在objc_msgSend函數中。首先通過obj的isa指針找到obj對應的class。在Class中先去cache中 通過SEL查找對應函數method(猜測cache中method列表是以SEL為key通過hash表來存儲的,這樣能提高函數查找速度),若 cache中未找到。再去methodList中查找,若methodlist中未找到,則取superClass中查找。若能找到,則將method加 入到cache中,以方便下次查找,并通過method中的函數指針跳轉到對應的函數中去執行。
?
轉載于:https://www.cnblogs.com/jingdizhiwa/p/5378165.html
總結
- 上一篇: Android富文本处理
- 下一篇: 从svn导入项目后处理一些报错信息