0丶介紹
Objc是一門動態(tài)語言草戈,所以它總是想辦法把一些決定工作從編譯連接推遲到運行時塌鸯。需要一個運行時系統(tǒng) (runtime system) 來執(zhí)行編譯后的代碼。
Runtime基本是用C和匯編寫的唐片,可見蘋果為了動態(tài)系統(tǒng)的高效而作出的努力丙猬。
官網(wǎng)文檔還提供關(guān)于傳統(tǒng)和現(xiàn)代版本Runtime的說明
In the legacy runtime, if you change the layout of instance variables in a class, you must recompile classes that inherit from it.
In the modern runtime, if you change the layout of instance variables in a class, you do not have to recompile classes that inherit from it.In addition, the modern runtime supports instance variable synthesis for declared properties (see Declared Properties in The Objective-C Programming Language).
一丶Objective-C運行時定義了幾種重要的類型。
-Class:定義Objective-C類
-Ivar:定義對象的實例變量费韭,包括類型和名字茧球。
-Protocol:定義正式協(xié)議。
-objc_property_t:定義屬性星持。叫這個名字可能是為了防止和Objective-C1.0中的用戶類型沖突抢埋,那時候還沒有屬性。
-Method:定義對象方法或類方法督暂。這個類型提供了方法的名字(就是**選擇器**)揪垄、參數(shù)數(shù)量和類型,以及返回值(這些信息合起來稱為方法的**簽名**)逻翁,還有一個指向代碼的函數(shù)指針(也就是方法的**實現(xiàn)**)饥努。
-SEL:定義選擇器。選擇器是方法名的唯一標(biāo)識符八回。
-IMP:定義方法實現(xiàn)酷愧。這只是一個指向某個函數(shù)的指針,該函數(shù)接受一個對象辽社、一個選擇器和一個可變長參數(shù)列表(varargs)伟墙,返回一個對象。
-Class:定義Objective-C類
-Ivar:定義對象的實例變量滴铅,包括類型和名字。
-Protocol:定義正式協(xié)議就乓。
-objc_property_t:定義屬性汉匙。叫這個名字可能是為了防止和Objective-C1.0中的用戶類型沖突拱烁,那時候還沒有屬性。
-Method:定義對象方法或類方法噩翠。這個類型提供了方法的名字(就是**選擇器**)戏自、參數(shù)數(shù)量和類型,以及返回值(這些信息合起來稱為方法的**簽名**)伤锚,還有一個指向代碼的函數(shù)指針(也就是方法的**實現(xiàn)**)擅笔。
-SEL:定義選擇器。選擇器是方法名的唯一標(biāo)識符屯援。
-IMP:定義方法實現(xiàn)猛们。這只是一個指向某個函數(shù)的指針,該函數(shù)接受一個對象狞洋、一個選擇器和一個可變長參數(shù)列表(varargs)弯淘,返回一個對象。
二丶API的速查手冊使用
1.objc_xxx 系列函數(shù)
函數(shù)名稱函數(shù)作用
objc_getClass獲取Class對象
objc_getMetaClass獲取MetaClass對象
objc_allocateClassPair分配空間,創(chuàng)建類(僅在 創(chuàng)建之后,注冊之前 能夠添加成員變量)
objc_registerClassPair注冊一個類(注冊后方可使用該類創(chuàng)建對象)
objc_disposeClassPair注銷某個類
objc_allocateProtocol開辟空間創(chuàng)建協(xié)議
objc_registerProtocol注冊一個協(xié)議
objc_constructInstance構(gòu)造一個實例對象(ARC下無效)
objc_destructInstance析構(gòu)一個實例對象(ARC下無效)
objc_setAssociatedObject為實例對象關(guān)聯(lián)對象
objc_getAssociatedObje*ct獲取實例對象的關(guān)聯(lián)對象
objc_removeAssociatedObjects清空實例對象的所有關(guān)聯(lián)對象
objc_msgSend發(fā)送ObjC消息
**objc_系列函數(shù)關(guān)注于宏觀使用,如類與協(xié)議的空間分配,注冊,注銷等操作**
2.class_xxx 系列函數(shù)**
函數(shù)名稱函數(shù)作用
class_addIvar為類添加實例變量
class_addProperty為類添加屬性
class_addMethod為類添加方法
class_addProtocol為類遵循協(xié)議
class_replaceMethod替換類某方法的實現(xiàn)
class_getName獲取類名
class_isMetaClass判斷是否為元類
objc_getProtocol獲取某個協(xié)議
objc_copyProtocolList拷貝在運行時中注冊過的協(xié)議列表
class_getSuperclass獲取某類的父類
class_setSuperclass設(shè)置某類的父類
class_getProperty獲取某類的屬性
class_getInstanceVariable獲取實例變量
class_getClassVariable獲取類變量
class_getInstanceMethod獲取實例方法
class_getClassMethod獲取類方法
class_getMethodImplementation獲取方法的實現(xiàn)
class_getInstanceSize獲取類的實例的大小
class_respondsToSelector判斷類是否實現(xiàn)某方法
class_conformsToProtocol判斷類是否遵循某協(xié)議
class_createInstance創(chuàng)建類的實例
class_copyIvarList拷貝類的實例變量列表
class_copyMethodList拷貝類的方法列表
class_copyProtocolList拷貝類遵循的協(xié)議列表
class_copyPropertyList拷貝類的屬性列表
**class_系列函數(shù)關(guān)注于類的內(nèi)部,如實例變量,屬性,方法,協(xié)議等相關(guān)問題**
3.object_xxx 系列函數(shù)**
函數(shù)名稱函數(shù)作用
object_copy對象copy(ARC無效)
object_dispose對象釋放(ARC無效)
object_getClassName獲取對象的類名
object_getClass獲取對象的Class
object_setClass設(shè)置對象的Class
object_getIvar獲取對象中實例變量的值
object_setIvar設(shè)置對象中實例變量的值
object_getInstanceVariable獲取對象中實例變量的值 (ARC中無效,使用object_getIvar)
object_setInstanceVariable設(shè)置對象中實例變量的值 (ARC中無效,使用object_setIvar)
**objcet_系列函數(shù)關(guān)注于對象的角度,如實例變量**
4.method_xxx 系列函數(shù)
函數(shù)名稱函數(shù)作用
method_getName獲取方法名
method_getImplementation獲取方法的實現(xiàn)
method_getTypeEncoding獲取方法的類型編碼
method_getNumberOfArguments獲取方法的參數(shù)個數(shù)
method_copyReturnType拷貝方法的返回類型
method_getReturnType獲取方法的返回類型
method_copyArgumentType拷貝方法的參數(shù)類型
method_getArgumentType獲取方法的參數(shù)類型
method_getDescription獲取方法的描述
method_setImplementation設(shè)置方法的實現(xiàn)
method_exchangeImplementations替換方法的實現(xiàn)
-
**method_系列函數(shù)關(guān)注于方法內(nèi)部,如果方法的參數(shù)及返回值類型和方法的實現(xiàn)**
****
5.property_xxx 系列函數(shù)**
函數(shù)名稱函數(shù)作用
property_getName獲取屬性名
property_getAttributes獲取屬性的特性列表
property_copyAttributeList拷貝屬性的特性列表
property_copyAttributeValue拷貝屬性中某特性的值
-
**property_系類函數(shù)關(guān)注與屬性*內(nèi)部,如屬性的特性等**
6.protocol_xxx 系列函數(shù)
函數(shù)名稱函數(shù)作用
protocol_conformsToProtocol判斷一個協(xié)議是否遵循另一個協(xié)議
protocol_isEqual判斷兩個協(xié)議是否一致
protocol_getName獲取協(xié)議名稱
protocol_copyPropertyList拷貝協(xié)議的屬性列表
protocol_copyProtocolList拷貝某協(xié)議所遵循的協(xié)議列表
protocol_copyMethodDescriptionList拷貝協(xié)議的方法列表
protocol_addProtocol為一個協(xié)議遵循另一協(xié)議
protocol_addProperty為協(xié)議添加屬性
protocol_getProperty獲取協(xié)議中的某個屬性
protocol_addMethodDescription為協(xié)議添加方法描述
protocol_getMethodDescription獲取協(xié)議中某方法的描述
7.ivar_xxx 系列函數(shù)
函數(shù)名稱函數(shù)作用
ivar_getName獲取Ivar名稱
ivar_getTypeEncoding獲取類型編碼
ivar_getOffset獲取偏移量
8.sel_xxx 系列函數(shù)
函數(shù)名稱函數(shù)作用
sel_getName獲取名稱
sel_getUid注冊方法
sel_registerName注冊方法
sel_isEqual判斷方法是否相等
9.imp_xxx 系列函數(shù)
函數(shù)名稱函數(shù)作用
imp_implementationWithBlock通過代碼塊創(chuàng)建IMP
imp_getBlock獲取函數(shù)指針中的代碼塊
imp_removeBlock移除IMP中的代碼塊
三丶簡單使用
1. 動態(tài)的添加對象的成員變量和方法
2. 動態(tài)交換兩個方法的實現(xiàn)
3. 實現(xiàn)分類也可以添加屬性
4. 實現(xiàn)NSCoding的自動歸檔和解檔
5. 實現(xiàn)字典轉(zhuǎn)模型的自動轉(zhuǎn)換
//1.檢查是否有某個屬性或變量
- (BOOL)hasAttribute:(NSString *)attName
{
BOOL flag = NO;
u_int count;
Ivar *ivars = class_copyIvarList([self class], &count);
for (int i = 0; i < count; i++)
{
const char *propertyName = ivar_getName(ivars[i]);
NSString *strName = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding];
if ([attName isEqualToString:strName])
{
flag = YES;
}
NSLog(@"===>%@", strName);
}
return flag;
}
//2.獲取屬性列表
unsigned int count;
objc_property_t *propertyList = class_copyPropertyList([self class], &count);
for (unsigned int i = 0; i< count; i++)
{
const char *name = property_getName(propertyList[i]);
NSLog(@"__%@",[NSString stringWithUTF8String:name]);
//得到屬性的各種信息
{ //得到屬性的各種信息
objc_property_t property = propertyList[i];
const char *a = property_getAttributes(property);
NSLog(@"屬性信息__%@",[NSString stringWithUTF8String:a]);
}
}
//3.交換2個方法
第一種:
Method oldMethod1 = class_getInstanceMethod([self class], @selector(viewDidLoad));
Method newMethod1 = class_getInstanceMethod([self class], @selector(xzbViewDidLoad));
method_exchangeImplementations(oldMethod1, newMethod1);
第二種:
Method oldMethod1 = class_getInstanceMethod([self class], @selector(viewDidLoad));
Method newMethod1 = class_getInstanceMethod([self class], @selector(xzbViewDidLoad));
method_setImplementation(oldMethod1, method_getImplementation(newMethod1));
//4.創(chuàng)建一個新類:objc_allocateClassPair
//創(chuàng)建一個新類:objc_allocateClassPair
Class newClass = objc_allocateClassPair([UIView class], "XZBCustomView", 0);
//給類增加新的方法:class_addMethod
class_addMethod(newClass, @selector(report), (IMP)ReportFunction, "v@:");
//注冊新類:objc_registerClassPair
objc_registerClassPair(newClass);
//實例;
id instanceOfNewClass = [[newClass alloc] init];
//調(diào)用report
[instanceOfNewClass performSelector:@selector(report)];
void ReportFunction(id self, SEL _cmd)
{
NSLog(@"This object is %p",self);//This object is 0x7fb2d2e0f900
NSLog(@"Class is %@,and super is %@",[self class],[self superclass]);// Class is XZBCustomView,and super is UIView
Class currenClass = [self class];
for (int i = 0; i<5; i++)
{
NSLog(@"%d %p",i,currenClass);
//獲取isa指針指向的對象object_getClass
currenClass = object_getClass(currenClass);
NSLog(@"NSObject:%p",[NSObject class]);
NSLog(@"object_getClass:%p",object_getClass([NSObject class]));
}
}