添加更新
RunTime消息機(jī)制:
? ? ? ? ? - (void)viewDidLoad {
[superviewDidLoad];
Person*p = [[Personalloc]init];
[peat];
// OC:運(yùn)行時(shí)機(jī)制,消息機(jī)制是運(yùn)行時(shí)機(jī)制最重要的機(jī)制
//消息機(jī)制:任何方法調(diào)用,本質(zhì)都是發(fā)送消息
// SEL:方法編號,根據(jù)方法編號就可以找到對應(yīng)方法實(shí)現(xiàn)
[pperformSelector:@selector(eat)];
//讓p發(fā)送消息
objc_msgSend(p,@selector(eat));
objc_msgSend(p,@selector(run:),10);
//類名調(diào)用類方法,本質(zhì)類名轉(zhuǎn)換成類對象
[Personeat];
//獲取類對象
ClasspersonClass = [Personclass];
[personClassperformSelector:@selector(eat)];
//運(yùn)行時(shí)
objc_msgSend(personClass,@selector(eat));
}
使用場景一:交換方法
? ? ? ? 例:用imageNamed加載圖片的時(shí)候,并不知道圖片是否加載成功
? ? ? ? ? ? //如果自定義方法:
? ? ? ? ? ?// 1.每次使用,都需要導(dǎo)入頭文件
? ? ? ? ? ? ? ? 2.當(dāng)一個(gè)項(xiàng)目開發(fā)太久,使用這個(gè)方式不靠譜
//所以只能擴(kuò)展類方法:
imageNamed:
//實(shí)現(xiàn)方法:底層調(diào)用WC_imageNamed
//本質(zhì):交換兩個(gè)方法的實(shí)現(xiàn)imageNamed和WC_imageNamed方法
//調(diào)用imageNamed其實(shí)就是調(diào)用WC_imageNamed
具體實(shí)現(xiàn):
#import"UIImage+Image.h"
#import
@implementationUIImage (Image)
// 加載這個(gè)分類的時(shí)候調(diào)用
+ (void)load
{
//交換方法實(shí)現(xiàn),方法都是定義在類里面
//class_getMethodImplementation:獲取方法實(shí)現(xiàn)
//class_getInstanceMethod:獲取對象
//class_getClassMethod:獲取類方法
//IMP:方法實(shí)現(xiàn)
//imageNamed
//Class:獲取哪個(gè)類方法
//SEL:獲取方法編號,根據(jù)SEL就能去對應(yīng)的類找方法
MethodimageNameMethod =class_getClassMethod([UIImageclass],@selector(imageNamed:));
//WC_imageNamed
MethodWC_imageNamedMethod =class_getClassMethod([UIImageclass],@selector(WC_imageNamed:));
//交換方法實(shí)現(xiàn)
method_exchangeImplementations(imageNameMethod,
WC_imageNamedMethod);
}
//運(yùn)行時(shí)
//先寫一個(gè)其他方法,實(shí)現(xiàn)這個(gè)功能
//在分類里面不能調(diào)用super,分類木有父類,如:
//+(UIImage *)imageNamed:(NSString *)name
//{
//[super imageNamed]
//}
+ (UIImage*)WC_imageNamed:(NSString*)imageName
{
//1.加載圖片
UIImage*image = [UIImageWC_imageNamed:imageName];
//2.判斷功能
if(image ==nil){
NSLog(@"加載image為空");
}
returnimage;
}
使用場景二:動態(tài)添加方法
? ? ? ? ?例:沒有在@interface聲明方法的情況下動態(tài)添加方法
具體實(shí)現(xiàn):
#import"Person.h"
#import
@implementation ?Person
//默認(rèn)一個(gè)方法都有兩個(gè)參數(shù),self,_cmd,隱式參數(shù)
// self:方法調(diào)用者
// _cmd:調(diào)用方法的編號
//動態(tài)添加方法,首先實(shí)現(xiàn)這個(gè)resolveInstanceMethod
// resolveInstanceMethod調(diào)用:當(dāng)調(diào)用了沒有實(shí)現(xiàn)的方法沒有實(shí)現(xiàn)就會調(diào)用resolveInstanceMethod
// resolveInstanceMethod作用:就知道哪些方法沒有實(shí)現(xiàn),從而動態(tài)添加方法
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
//NSLog(@"%@",NSStringFromSelector(sel));
//動態(tài)添加eat方法
if(sel ==@selector(eat:)){
/*
cls:給哪個(gè)類添加方法
SEL:添加方法的方法編號是什么
IMP:方法實(shí)現(xiàn),函數(shù)入口,函數(shù)名
types:方法類型
*/
// @:對象:SEL
class_addMethod(self, sel, (IMP)aaaa,"v@:@");
//處理完
returnYES;
}
return[superresolveInstanceMethod:sel];
}
//定義函數(shù)
//沒有返回值,參數(shù)(id,SEL)
//void(id,SEL)
voidaaaa(idself,SEL_cmd,idparam1)
{
NSLog(@"調(diào)用eat %@ %@
%@",self,NSStringFromSelector(_cmd),param1);
}
@end
適用場景三:給分類添加屬性
? ? ? 例:在分類的@interface中沒有聲明屬性的情況下,動態(tài)的添加屬性
適用場景四:字典轉(zhuǎn)模型
? ? ? ? ?例:跟KVC一樣的字典轉(zhuǎn)模型功能
具體實(shí)現(xiàn):
//NSObject+Model.m
#import"NSObject+Model.h"
#import
/*
Ivar ?ivar1;
Ivar ?ivar2;
Ivar ?ivar3;
Ivar ?a[] = {ivar3,ivar1,ivar2};
Ivar ?*ivar = &a;
*/
@implementationNSObject (Model)
+ (instancetype)modelWithDict:(NSDictionary*)dict{
//創(chuàng)建對應(yīng)類的對象
idobjc = [[selfalloc]init];
//runtime:遍歷模型中所有成員屬性,去字典中查找
//屬性定義在哪,定義在類,類里面有個(gè)屬性列表(數(shù)組)
//遍歷模型所有成員屬性
//ivar:成員屬性
//class_copyIvarList:把成員屬性列表復(fù)制一份給你
//Ivar *:指向Ivar指針
//Ivar *:指向一個(gè)成員變量數(shù)組
//class:獲取哪個(gè)類的成員屬性列表
//count:成員屬性總數(shù)
unsignedintcount =0;
Ivar*ivarList =class_copyIvarList(self, &count);
for(inti =0; i < count; i++) {
//獲取成員屬性
Ivarivar = ivarList[i];
//獲取成員名
NSString*propertyName = [NSStringstringWithUTF8String:ivar_getName(ivar)];
//成員屬性類型
NSString*propertyType = [NSStringstringWithUTF8String:ivar_getTypeEncoding(ivar)];
//獲取key
NSString*key = [propertyNamesubstringFromIndex:1];
//獲取字典的value
idvalue = dict[key];
//給模型的屬性賦值
// value:字典的值
// key:屬性名
if(value) {
//KVC賦值:不能傳空
[objcsetValue:valueforKey:key];
}
//NSLog(@"%@",key);
//NSLog(@"%@ %@",propertyType , propertyName);
}
returnobjc;
}
@end