OC語言是基于C語言進(jìn)行封裝的一種面向?qū)ο蟮恼Z言,因此OC的底層就是C,runtime則是用來鏈接OC與C绪杏,用C語言寫的一個庫,完成OC所不能完成的事,
以下是Runtime中比較常用的一些方法:
Ivar *class_copyIvarList(Class cls, unsigned int *outCount) //獲取所有成員變量
const char *ivar_getName(Ivar v) 獲取某個成員變量的名字
const char *ivar_getTypeEncoding(Ivar v) //獲取某個成員變量的類型編碼
Ivar class_getInstanceVariable(Class cls, const char *name) //獲取某個類中指定名稱的成員變量
id object_getIvar(id obj, Ivar ivar) //獲取某個對象中的某個成員變量的值
void object_setIvar(id obj, Ivar ivar, id value) //設(shè)置某個對象的某個成員變量的值
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy) //為某個類關(guān)聯(lián)某個對象
id objc_getAssociatedObject(id object, const void *key) //獲取到某個類的某個關(guān)聯(lián)對象
void objc_removeAssociatedObjects(id object) //移除已經(jīng)關(guān)聯(lián)的對象
在OC中尖啡,給一個類添加方法和可以使用延展,但使用延展的方法通常只能在本類中使用剩膘,在外界就訪問不到了衅斩,如何才能在其他類中也使用這個類的私有方法和屬性呢?
首先必須導(dǎo)入#import <objc/runtime.h>
//編碼
- (void)encodeWithCoder:(NSCoder *)aCoder
{
unsigned int outCount;
Ivar *ivarList = class_copyIvarList([Person class], &outCount);
for (NSInteger i = 0; i < outCount; i++) {
const char *cName = ivar_getName(ivarList[i]);
NSString *name = [NSString stringWithUTF8String:cName];
[aCoder encodeObject:[self valueForKey:name] forKey:name];
}
}
//解碼
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
unsigned int outCount;
Ivar *ivarList = class_copyIvarList([Person class], &outCount);
for (NSInteger i = 0; i < outCount; i ++) {
const char *cName = ivar_getName(ivarList[i]);
NSString *name = [NSString stringWithUTF8String:cName];
[self setValue:[aDecoder decodeObjectForKey:name] forKey:name];
}
}
return self;
}
- (NSString *)description
{
/**
* class:要獲取的類名
* @param outCount 通過這一個函數(shù)執(zhí)行之后會將成員變量的個數(shù)賦值到此
* int * char * 表示int,char數(shù)組
*/
unsigned int outCount;
//獲取到所有的成員變量
Ivar *ivarList = class_copyIvarList([Person class], &outCount);
for (NSInteger i = 0; i < outCount; i++) {
//每次獲取一個成員變量
Ivar ivar = ivarList[i];
//獲取成員變量的名字和類型編碼
NSLog(@"name = %s,type = %s",ivar_getName(ivar),ivar_getTypeEncoding(ivar));
}
return nil;
}
然后在外界就可以使用這個類里面的屬性和方法了
有時候援雇,調(diào)用值申明沒有實現(xiàn)的方法就會造成了程序Cresh矛渴,runtime中提供了了幾個方法來避免這一問題
1 + resolveInstanceMethod:(SEL)sel // 為一個實例方法動態(tài)添加實現(xiàn) + resolveClassMethod:(SEL)sel // 為一個類方法動態(tài)添加實現(xiàn)
2 - (id)forwardingTargetForSelector:(SEL)aSelector
//為沒有實現(xiàn)的方法指定一個對象
3 - (void)forwardInvocation:(NSInvocation *)anInvocation
//子類重載這個方法為消息指定其他對象
比如我在.h中定義了walkOnTheStreet:這個方法椎扬,但是并沒有在.m中實現(xiàn)惫搏,那可以調(diào)用使用以上幾個方法來添加實現(xiàn)
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
NSString *selString = NSStringFromSelector(sel);
if ([selString isEqualToString:@"walkOnTheStreet:"]) {
為一個沒有實現(xiàn)的方法動態(tài)添加實現(xiàn)
cls:類
IMP:要添加的實現(xiàn)
types:動態(tài)添加的實現(xiàn)的類型編碼
class_addMethod(self, @selector(walkOnTheStreet:), (IMP)walkFunc, "V@:@");
}
return [super resolveInstanceMethod:sel];
}
有了這個方法,即使我們在viewDidLoad中調(diào)用沒實現(xiàn)的方法也不會Cresh蚕涤,runtime會幫我們實現(xiàn)筐赔,它的強大之處是實現(xiàn)方法可以在別的類中,只要和class_addMethod指定的方法名相同即可