我們接著上一篇文章將,熟悉iOS的朋友都知道,當(dāng)我們?yōu)橐粋€(gè)類創(chuàng)建延展的時(shí)候,我們只能為其添加方法,不能為其添加屬性.這個(gè)特性我們都知道,但是知道為什么嗎?其實(shí)這是因?yàn)樵诜诸愔惺褂聾property是不會(huì)自動(dòng)實(shí)現(xiàn)getter和setter的,并且也不會(huì)生成_開(kāi)頭的屬性。所以在類目中我們只能添加方法,不能為類添加屬性/成員變量,但是當(dāng)我們用了運(yùn)行時(shí)機(jī)制以后動(dòng)態(tài)的在類目中為一個(gè)類添加屬性就可以做到.給一個(gè)類聲明屬性,其實(shí)本質(zhì)就是給這個(gè)類添加關(guān)聯(lián),并不是直接把這個(gè)值的內(nèi)存空間添加到類上.
一、首先為Person類創(chuàng)建一個(gè)類目,在聲明文件中隨便聲明一個(gè)屬性
//動(dòng)態(tài)關(guān)聯(lián)屬性
@property(nonatomic,copy)NSString *sex;
二、在實(shí)現(xiàn)文件中導(dǎo)入運(yùn)行時(shí)頭文件#import <objc/runtime.h>
,并重新屬性的setter方法和getter方法
// 定義關(guān)聯(lián)的key
const char *key = "mm";
//實(shí)現(xiàn)setter方法
-(void)setSex:(NSString *)sex{
//設(shè)置關(guān)聯(lián)
// 第一個(gè)參數(shù):給哪個(gè)對(duì)象添加關(guān)聯(lián)
// 第二個(gè)參數(shù):關(guān)聯(lián)的key捻脖,通過(guò)這個(gè)key獲取
// 第三個(gè)參數(shù):關(guān)聯(lián)的value
// 第四個(gè)參數(shù):關(guān)聯(lián)的策略
objc_setAssociatedObject(self, key, sex, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
//實(shí)現(xiàn)getter方法
-(NSString *)sex{
return objc_getAssociatedObject(self, key);;
}
三、在控制器中導(dǎo)入類的延展,并未擴(kuò)展的屬性賦值
//用RunTime在類目中添加屬性
per.sex = @"男";
NSLog(@"%@",per.sex);
那么怎么動(dòng)態(tài)的添加方法呢?在我們?cè)瓉?lái)的person類的實(shí)現(xiàn)文件中
//當(dāng)調(diào)用類方法不存在時(shí)會(huì)走下面的方法
//+(BOOL)resolveClassMethod:(SEL)sel
//任何一個(gè)函數(shù)都會(huì)有以下兩個(gè)參數(shù)(默認(rèn)方法都有兩個(gè)隱式參數(shù))
void eattttttt(id self,SEL _cmd){
NSLog(@"吃了--%@%@",self,NSStringFromSelector(_cmd));
}
void eeee(id self,SEL _cmd,id objc){
NSLog(@"吃了--%@",objc);
}
//當(dāng)調(diào)用的對(duì)象方法不存在時(shí)會(huì)走下面的方法
//當(dāng)一個(gè)對(duì)象調(diào)用未實(shí)現(xiàn)的方法尺借,會(huì)調(diào)用這個(gè)方法處理,并且會(huì)把對(duì)應(yīng)的方法列表傳過(guò)來(lái).
+(BOOL)resolveInstanceMethod:(SEL)sel{
NSLog(@"??/當(dāng)調(diào)用的對(duì)象方法不存在時(shí)會(huì)走下面的方法");
//sel == NSSelectorFromString(@"eat")
if (sel == @selector(eattttttt)) {
/*
cls 類的類型
name 方法編號(hào)
IMP 方法實(shí)現(xiàn),本質(zhì)就是一個(gè)指針
type 返回值和參數(shù)
*/
//command+ shift+ 0 查看文檔
//動(dòng)態(tài)添加eattttttt方法
// 注意:這里需要強(qiáng)轉(zhuǎn)成IMP類型
class_addMethod(self, sel, (IMP)eattttttt, "v");
}else if (sel == @selector(eat1:)){
class_addMethod(self, sel, (IMP)eeee, "v@:@");
}
// 先恢復(fù), 不然會(huì)覆蓋系統(tǒng)的方法
return [super resolveInstanceMethod:sel];
}
在聲明person對(duì)象并對(duì)其方法進(jìn)行調(diào)用的時(shí)候,使用performSelector方法就可以了
Person *per = [[Person alloc]init];
[per performSelector:@selector(eattttttt)];
[per performSelector:@selector(eat1:) withObject:@"滿漢全席"];
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者