objc物件說明
objc_object 物件
/// 表示類的例項物件
struct objc_object {
//isa 為指向類的指標
Class _Nonnull isa;
};
什麼是class,這就是class
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
struct objc_class {
//isa 指向該類的元類
Class _Nonnull isa;
//父類
Class _Nullable super_class;
//例項物件大小
long instance_size;
//屬性列表
struct objc_ivar_list * _Nullable ivars;
//例項方法列表
struct objc_method_list * _Nullable * _Nullable methodLists;
//物件快取
struct objc_cache * _Nonnull cache;
//協議列表
struct objc_protocol_list * _Nullable protocols;
} OBJC2_UNAVAILABLE;
什麼是 Ivar
/// An opaque type that represents an instance variable.
typedef struct objc_ivar *Ivar;
struct objc_ivar {
//變數名稱
char * _Nullable ivar_name;
//變數型別
char * _Nullable ivar_type
//地址偏移量
int ivar_offset;
//變數空間大小
int space;
}
對 ivar 的訪問就可以通過 物件地址
+ ivar偏移位元組的方法。但是這又引發一個問題,我們增加了父類的ivar,這個時候佈局就出錯了,我們就不得不重新編譯子類來恢復相容性。使用Non Fragile ivars時,Runtime會進行檢測來調整類中新增的ivar的偏移量。 這樣我們就可以通過物件地址
+ 基類大小 + ivar偏移位元組的方法來計算出ivar相應的地址,並訪問到相應的ivar
ivar 的用法
執行時規定,只能在objc_allocateClassPair與objc_registerClassPair兩個函式之間為類新增變數
//額外空間 未知,通常設定為 0
Class clazz = objc_allocateClassPair(父類class,類名,額外空間);
//以NSString*為例
//變數size sizeof(NSString)
//對齊 指標型別的為log2(sizeof(NSString*))
//型別 @encode(NSString*)
BOOL flag = class_addIvar(clazz,變數名,變數size,對齊,型別);
objc_registerClassPair(clazz);
Ivar的
//獲取Ivar的名稱
const char *ivar_getName(Ivar v);
//獲取Ivar的型別編碼,
const char *ivar_getTypeEncoding(Ivar v)
//通過變數名稱獲取類中的例項成員變數
Ivar class_getInstanceVariable(Class cls, const char *name)
//通過變數名稱獲取類中的類成員變數
Ivar class_getClassVariable(Class cls, const char *name)
//獲取指定類的Ivar列表及Ivar個數
Ivar *class_copyIvarList(Class cls, unsigned int *outCount)
//獲取例項物件中Ivar的值
id object_getIvar(id obj, Ivar ivar)
//設定例項物件中Ivar的值
void object_setIvar(id obj, Ivar ivar, id value)
還能這樣用
//在執行時建立繼承自NSObject的People類
Class People = objc_allocateClassPair([NSObject class], "People", 0);
//新增_name成員變數
BOOL flag1 = class_addIvar(People, "_name", sizeof(NSString*), log2(sizeof(NSString*)), @encode(NSString*));
if (flag1) {
NSLog(@"NSString*型別 _name變數新增成功");
}
//新增_age成員變數
BOOL flag2 = class_addIvar(People, "_age", sizeof(int), sizeof(int), @encode(int));
if (flag2) {
NSLog(@"int型別 _age變數新增成功");
}
//完成People類的建立
objc_registerClassPair(People);
unsigned int varCount;
//拷貝People類中的成員變數列表
Ivar * varList = class_copyIvarList(People, &varCount);
for (int i = 0; i<varCount; i++) {
NSLog(@"%s",ivar_getName(varList[i]));
}
//釋放varList
free(varList);
//建立People物件p1
id p1 = [[People alloc]init];
//從類中獲取成員變數Ivar
Ivar nameIvar = class_getInstanceVariable(People, "_name");
Ivar ageIvar = class_getInstanceVariable(People, "_age");
//為p1的成員變數賦值
object_setIvar(p1, nameIvar, @"張三");
object_setIvar(p1, ageIvar, @33);
//獲取p1成員變數的值
NSLog(@"%@",object_getIvar(p1, nameIvar));
NSLog(@"%@",object_getIvar(p1, ageIvar));
什麼是 Property
/// Defines a property attribute
typedef struct {
//屬性名
const char * _Nonnull name; /**< The name of the attribute */
//屬性值
const char * _Nonnull value; /**< The value of the attribute (usually empty) */
} objc_property_attribute_t;
特性相關編碼
屬性的特性字串 以 T@encode(type) 開頭, 以 V例項變數名稱 結尾,中間以特性編碼填充,通過property_getAttributes即可檢視
特性編碼 具體含義
R readonly
C copy
& retain
N nonatomic
G(name) getter=(name)
S(name) setter=(name)
D @dynamic
W weak
P 用於垃圾回收機制
為類新增Property
BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
Property的相關操作
//替換類中的屬性
void class_replaceProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
//獲取類中的屬性
objc_property_t class_getProperty(Class cls, const char *name)
//拷貝類中的屬性列表
objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
//獲取屬性名稱
const char *property_getName(objc_property_t property)
//獲取屬性的特性
const char *property_getAttributes(objc_property_t property)
//拷貝屬性的特性列表
objc_property_attribute_t *property_copyAttributeList(objc_property_t property, unsigned int *outCount)
//拷貝屬性的特性的值
char *property_copyAttributeValue(objc_property_t property, const char *attributeName)
Property其他用法
Class People = objc_allocateClassPair([NSObject class], "People", 0);
objc_registerClassPair(People);
//T@
objc_property_attribute_t attribute1;
attribute1.name = "T";
attribute1.value=@encode(NSString*);
//Noatomic
objc_property_attribute_t attribute2 = {"N",""};//value無意義時通常設定為空
//Copy
objc_property_attribute_t attribute3 = {"C",""};
//V_屬性名
objc_property_attribute_t attribute4 = {"V","_name"};
//特性陣列
objc_property_attribute_t attributes[] ={attribute1,attribute2,attribute3,attribute4};
//向People類中新增名為name的屬性,屬性的4個特性包含在attributes中
class_addProperty(People, "name", attributes, 4);
//獲取類中的屬性列表
unsigned int propertyCount;
objc_property_t * properties = class_copyPropertyList(People, &propertyCount);
for (int i = 0; i<propertyCount; i++) {
NSLog(@"屬性的名稱為 : %s",property_getName(properties[i]));
NSLog(@"屬性的特性字串為: %s",property_getAttributes(properties[i]));
}
//釋放屬性列表陣列
free(properties);
關於 Method
Method 定義
/// Defines a method
struct objc_method_description {
SEL _Nullable name; /**< The name of the method */
char * _Nullable types; /**< The types of the method arguments */
};
typedef struct objc_method *Method;
struct objc_method {
SEL method_name; // 方法名
char *method_types;
IMP method_imp; // 方法實現
}
IMP, IMP實際上是一個函式指標,指向方法實現的首地址
相關操作
id (*IMP)(id, SEL, ...)
// 呼叫指定方法的實現
id method_invoke ( id receiver, Method m, ... );
// 呼叫返回一個資料結構的方法的實現
void method_invoke_stret ( id receiver, Method m, ... );
// 獲取方法名
SEL method_getName ( Method m );
// 返回方法的實現
IMP method_getImplementation ( Method m );
// 獲取描述方法引數和返回值型別的字串
const char * method_getTypeEncoding ( Method m );
// 獲取方法的返回值型別的字串
char * method_copyReturnType ( Method m );
// 獲取方法的指定位置引數的型別字串
char * method_copyArgumentType ( Method m, unsigned int index );
// 通過引用返回方法的返回值型別字串
void method_getReturnType ( Method m, char *dst, size_t dst_len );
// 返回方法的引數的個數
unsigned int method_getNumberOfArguments ( Method m );
// 通過引用返回方法指定位置引數的型別字串
void method_getArgumentType ( Method m, unsigned int index, char *dst, size_t dst_len );
// 返回指定方法的方法描述結構體
struct objc_method_description * method_getDescription ( Method m );
// 設定方法的實現
IMP method_setImplementation ( Method m, IMP imp );
// 交換兩個方法的實現
void method_exchangeImplementations ( Method m1, Method m2 );
未完,待續。。。。。
Protocol
objc_ivar_list
objc_method_list
objc_symtab
objc_cache
相關文章
- objc原始碼解析-ObjectiveC物件結構原始碼Object物件
- Yul語言及物件說明——Solidity中文文件(9)物件Solid
- 說明
- ObjC Runtime簡析-- objc_MsgSendOBJGse
- 用愚公移山說明Javascript建立物件的各種姿勢JavaScript物件
- 使用說明
- Hack 說明
- 專利說明書及其說明書附圖
- 舉例說明陣列和物件的迭代方法分別有哪些?陣列物件
- 舉例說明物件導向程式設計有什麼缺點?物件程式設計
- openssh版本更新與說明 openssl版本更新與說明
- SDWebImage中文說明Web
- git 操作說明Git
- MOBIM介面說明
- Oracle Latch 說明Oracle
- SpringBoot整合說明Spring Boot
- FreeSql 使用說明SQL
- postman 使用說明Postman
- QLExpress使用說明Express
- WebApiClientCore使用說明WebAPIclient
- ThinkSNS 更新說明
- Jupiter 使用說明
- certbot 使用說明
- cmake使用說明
- 轉換說明
- rust配置說明Rust
- flowable 更新說明
- ApplicationContextAware使用說明APPContext
- Ironic映象說明
- 說明符%d
- winscp操作說明,winscp操作說明的詳細解讀
- CentOS 7升級核心簡明說明CentOS
- Fresco的封裝和使用說明以及獲取快取中的Bitmap物件封裝快取物件
- oradebug的使用說明
- axios使用說明書iOS
- MobIM-API說明API
- wc 命令使用說明
- mysqldump引數說明MySql