為什么使用類目
是一種為現(xiàn)有的類添加新方法的方式
有時需要對現(xiàn)有的類添加一些方法,之前都是通過繼承相關(guān)的類,然后再子類中擴(kuò)展我們需要的相應(yīng)的方法.
Objective-C是一種動態(tài)語言,可以給現(xiàn)有的類添加新的方法,這便是對類目的延展.
類目(category):為已知的類添加新的方法计呈,無論是否知道類的源代碼,這些類包括自己定義的類和系統(tǒng)已有的類。
類目的作用主要有三個方面:
1、將類的實(shí)現(xiàn)分散到多個不同的文件中,將多個類目的聲明放入同一個.h文件中闷畸,將實(shí)現(xiàn)放入多個.m方法中。
2、使用類目創(chuàng)建對私有方法的前向引用乎完,就是為類創(chuàng)建私有方法。
3品洛、向?qū)ο筇砑臃钦絽f(xié)議树姨,現(xiàn)在逐漸被正式協(xié)議做替代。
類目的實(shí)現(xiàn)
類目聲明之后需要對類擴(kuò)展出來的方法進(jìn)行實(shí)現(xiàn)
使用擴(kuò)展后的方法
#import <Foundation/Foundation.h>
#import "NSString+MyNumber.h"http://添加類目頭文件
int main(int argc, const char * argv[])
{
@autoreleasepool
{
//創(chuàng)建四個字符串
NSString *str1=@"gdsfgsdfgfdgdfs";
NSString *str2=@"fgsagsdfgfdsg";
NSString *str3=@"打開分為飛大廈俄方飛";
NSString *str4=@"jfghjfghjfghj";
//求出每一個字符串的長度
// int l1=(int)[str1 length];
// int l2=(int)[str2 length];
// int l3=(int)[str3 length];
// int l4=(int)[str4 length];
//
// //轉(zhuǎn)為對象
// NSNumber *m1=[NSNumber numberWithInt:l1];
// NSNumber *m2=[NSNumber numberWithInt:l2];
// NSNumber *m3=[NSNumber numberWithInt:l3];
// NSNumber *m4=[NSNumber numberWithInt:l4];
//創(chuàng)建一個可變的字典
NSMutableDictionary *mDic=[NSMutableDictionary new];
//添加對象到字典中
// [mDic setObject:m1 forKey:str1];
// [mDic setObject:m2 forKey:str2];
// [mDic setObject:m3 forKey:str3];
// [mDic setObject:m4 forKey:str4];
//使用類目后修改為
[mDic setObject:[str1 getStrLength] forKey:str1];
[mDic setObject:[str2 getStrLength] forKey:str2];
[mDic setObject:[str3 getStrLength] forKey:str3];
[mDic setObject:[str4 getStrLength] forKey:str4];
//輸出
NSLog(@"%@",mDic);
}
return 0;
}
注意類目里面只能寫方法,不能寫聲明和屬性,所以,類目不能作為接口來用
類目的局限性
-類目無法向已有類中添加實(shí)例變量
-如果類目中的方法和已有類中的方法名稱沖突時桥状,類目中的方法優(yōu)先級高,如果方法名沖突,已有類中的原始方法便無法使用
-在使用類目的時候,最好是將自己擴(kuò)展的方法和原始方法區(qū)分開來
類目的作用
有三個方面:
1.將類的實(shí)現(xiàn)分散到多個不同的文件中
-將多個類目的聲明放入同一個.h文件中
-將實(shí)現(xiàn)放入多個.m方法中
2.使用類目創(chuàng)建對私有方法的前向引用
-就是為類創(chuàng)建私有方法
3.向?qū)ο筇砑臃钦絽f(xié)議
-現(xiàn)在逐漸被正式協(xié)議做替代
利用類目分散實(shí)現(xiàn)類
-類的@implementation部分只能寫在一個.m文件中
-對于大型的類,可以使用類目將類的實(shí)現(xiàn)間接的放入多個.m文件中
-將多個類目的聲明放入同一個.h文件中帽揪,包括多個類目聲明的@interface和@end
類私有的方法
-Objective-C中沒有絕對意義上的私有方法
-在.h文件中聲明的方法都屬于公開的方法,意味著開放給別人調(diào)用
-如果不想公開某些方法辅斟,可以不在.h文件中聲明
-這樣的方法可以被本類中的其他方法所調(diào)用
-如果在類外面強(qiáng)行調(diào)用這些未公開的方法转晰,也能調(diào)用,但是會有編譯器警告
類的延展
延展(extension):
在自己類的實(shí)現(xiàn)文件中添加類目(匿名類目)來聲明私有方法.(只有本類的.m文件中才能使用)
類的延展可以讓類方法成為類的私有方法
將私有方法聲明到一個匿名類目中,并且將這個匿名類目放到類的.m文件里
然后在類的.m的@implementation部分將這個匿名類目中的私有方法進(jìn)行實(shí)現(xiàn)
這樣的也能夠?qū)懗鏊接蟹椒ú樾希峭瑯右部梢詮?qiáng)行在類外部調(diào)用蔗崎,也會有編譯器警告
使用類目對私有方法反向引用
-如果私有方法的聲明放入一個匿名類目中,并且這個類目放入一個.h文件中那么這個.h文件可以看做私有的API
-私有API可以不公開侠坎,只開放給許可者來調(diào)用
然后在使用私有API時將那個.h文件導(dǎo)入蚁趁,然后調(diào)用私有方法,編譯器警告便會消失
respondsToSelector
用來檢查某一個對象能否調(diào)用某一個方法(檢查方法時候有實(shí)現(xiàn))
創(chuàng)建了NSObject的類目之后实胸,類目中聲明方法對于NSObject的子類來說如何檢查是否實(shí)現(xiàn)了哪個方法
因?yàn)榭赡芤{(diào)用某個NSObject類目中聲明的方法他嫡,在調(diào)用時需要判斷是否能夠響應(yīng)才行,否則會造成程序崩潰
MyClass *mc= [MyClass new];
if([mc respondsToSelector:@selector(test)])
{
[mc test];
}
else
{
NSLog(@"未實(shí)現(xiàn)test方法庐完!");
}
Objective-C中的協(xié)議
協(xié)議是一個方法列表钢属,采用協(xié)議時需要在聲明類時說明要采用的協(xié)議
協(xié)議的聲明
協(xié)議就是一種標(biāo)準(zhǔn),用來定義了實(shí)現(xiàn)什么,不關(guān)心具體怎么實(shí)現(xiàn)
OC的協(xié)議是由@protocol聲明的一組方法列表
要求其它的類去實(shí)現(xiàn)门躯,相當(dāng)于@interface部分的聲明
@required標(biāo)注的方法為必須實(shí)現(xiàn)方法(默認(rèn)不寫為必須實(shí)現(xiàn))
@optional標(biāo)注的方法為可以選擇實(shí)現(xiàn)
@protocol 協(xié)議名稱
//方法列表
@end
協(xié)議的實(shí)現(xiàn)
方式:
接口文件 一個類可以通過協(xié)議,用來遵循多個類中的方法,這樣可以做到多繼承的效果
@interface ClassName : 父類名 <協(xié)議1,協(xié)議2…>
@end
實(shí)現(xiàn)文件
@implementation ClassName
//實(shí)現(xiàn)協(xié)議中的方法
@end
具體實(shí)現(xiàn)方法
@protocol MyProtocol <NSObject>
@required//必須實(shí)現(xiàn)
-(int) addX:(int) x andY:(int) y;
@optional//可選實(shí)現(xiàn)
-(int) substructX:(int) x andY:(int) y;
@end
協(xié)議和數(shù)據(jù)類型
聲明實(shí)例變量或方法可以指定協(xié)議名稱
id類型可以指向任何類型的
@interface MyClass
{
id<MyProtocol> myVar;
}
@end
要求傳入的參數(shù)必須采用MyProtocol協(xié)議
-(void) methodName:(id<MyProtocol>) obj
{
//方法代碼
}
檢查對象是否實(shí)現(xiàn)了某個協(xié)議
可以通過對象的下列方法來判斷是否遵循某協(xié)議(confrorms:遵守)
conformsToProtocol:@protocol (協(xié)議名)
在此創(chuàng)建一個代理使用的實(shí)例
先創(chuàng)建兩個類,繼承NSObjective
一個被代理的類,命名為HouseMan
一個代理的類,命名Medium
HouseMan.h接口文件中實(shí)現(xiàn)
// 房東
#import <Foundation/Foundation.h>
//1.聲明協(xié)議
@protocol GetHoseProtocol <NSObject>
-(void)getRent;//房租的方法
@end
@interface HouseMan : NSObject
//2.創(chuàng)建一個代理人的屬性 在此簽訂一個協(xié)議
@property(nonatomic,assign)id<GetHoseProtocol> delegate;
//3.協(xié)議的方法
-(void)houseRent;
@end
HouseMan.m實(shí)現(xiàn)文件中實(shí)現(xiàn)
//4.實(shí)現(xiàn)需要代理的方法
-(void)houseRent
{
[self.delegate getRent];//呼叫被代理人去做
}
Medium.h接口文件中實(shí)現(xiàn)
#import <Foundation/Foundation.h>
#import "HouseMan.h"http://5.包含代理人的頭文件
@interface Medium : NSObject<GetHoseProtocol>//6.被代理人和代理人簽訂協(xié)議
//7聲明代理人的屬性
@property (nonatomic, strong) NSString *name;
Medium.m實(shí)現(xiàn)文件中
#import "Medium.h"
@implementation Medium
//7.實(shí)現(xiàn)被代理人的方法
-(void)getRent
{
NSLog(@"正在收房租");
}
@end
最后在main.m文件中
#import <Foundation/Foundation.h>
//包含頭文件
#import "HouseMan.h"
#import "Medium.h"
int main(int argc, const char * argv[])
{
@autoreleasepool
{
//創(chuàng)建代理對象
Medium *m=[Medium new];
m.name=@"房屋中介";
//創(chuàng)建被代理對象
HouseMan *h=[HouseMan new];
//給代理對象賦值
h.delegate=m;
//被代理人呼叫代理人實(shí)現(xiàn)方法 這個方法是在被代理人種實(shí)現(xiàn)的
[h houseRent];
}
return 0;
}
設(shè)計模式
設(shè)計模式(Design pattern)是一套被反復(fù)使用淆党、多數(shù)人知曉的、經(jīng)過分類編目的讶凉、代碼設(shè)計經(jīng)驗(yàn)的總結(jié)染乌。
-設(shè)計模式是某個具體編程問題的通用化,可以復(fù)用的解決方案
-沒有一種可以從前一個方案中完全復(fù)用代碼的情況懂讯,但是可以使用前一次的解決問題時使用的思想
-設(shè)計模式可以在遇到編程問題時會想起一個正確的解決方案
-常見的設(shè)計模式有:單例模式荷憋、委托(代理)模式、觀察者模式褐望、職責(zé)鏈模式等等
委托模式
在委托模式中勒庄,程序中的一個對象代表另外一個對象執(zhí)行某個動作,或者與之相互協(xié)作共同完成某個任務(wù)。
Cocoa Touch廣泛使用委托(delegate)瘫里,它是負(fù)責(zé)為其他對象處理特定任務(wù)的類实蔽。通過委托,我們能夠在某些預(yù)定義時間內(nèi)為發(fā)布委托的類做一些工作谨读。
所謂代理局装,就是指一方授予他方代理權(quán),他方依代理權(quán)與第三方進(jìn)行法律行為劳殖,其行為后果由一方承擔(dān)的一種民事法律制度贼邓。委托是一方將一定的事務(wù)委諸于另一方實(shí)施的法律制度。
委托和代理的區(qū)別:
第一闷尿,委托規(guī)范的是委托人和受托人雙方之間的關(guān)系塑径;而代理規(guī)范的是本人、代理人和第三人的關(guān)系填具。
第二统舀,代理關(guān)系中代理人代理的對象是進(jìn)行意思表示和接受意思表示的行為匆骗;而委托中受托人代為實(shí)施的行為可以是法律行為,也可以是事實(shí)行為誉简。
第三碉就,代理包括對內(nèi)和對外兩種關(guān)系,對內(nèi)是代理人和被代理人之間的關(guān)系闷串,而對外是代理人和第三人之間的關(guān)系瓮钥;而委托只是委托人和受托人之間的關(guān)系。
簡單的總結(jié):
-委托就是有兩個對象,一個變化時,另外一個能夠知道上面一個的變化.
-一個對象保存另外一個對象的引用,被引用的對象實(shí)現(xiàn)事先確定的協(xié)議,這個協(xié)議用來把對象中的變化通知給被引用的對象
-委托不一定使用到協(xié)議,使用類目一樣能完成,或者協(xié)議類目都不知用,同樣能做到.
delegate屬性都是assign而不是retain為了避免循環(huán)引用造成的內(nèi)存泄露烹吵。
循環(huán)引用的問題這樣理解:
-比如在main函數(shù)中創(chuàng)建了兩個類的對象A和B碉熄,現(xiàn)在引用計數(shù)都是1。現(xiàn)在讓A和B互相引用(A有一個屬性是B對象肋拔,屬性說明是retain锈津;B有一個屬性是A對象,屬性說明是retain)凉蜂,現(xiàn)在兩個對象的引用計數(shù)都增加了1琼梆,都變成了2。
-現(xiàn)在執(zhí)行 [A release]; [B release]; 此時創(chuàng)建對象的main函數(shù)已經(jīng)釋放了自己對對象的所有權(quán)窿吩,但是此時A和B的引用計數(shù)都還是1茎杂,因?yàn)樗麄兓ハ嘁昧恕?br> -這時你發(fā)現(xiàn)A和B將無法釋放,因?yàn)橐脶尫臕必須先釋放B纫雁,在B的dealloc方法中再釋放A煌往。同理,要想釋放B必須先釋放A先较,在A的dealloc方法中再釋放B携冤。所以這兩個對象將一直存在在內(nèi)存中而不釋放悼粮。這就是所謂的循環(huán)引用的問題闲勺。
-要想解決這個問題,一般的方法可以將引用的屬性設(shè)置為assign,而不是retain來處理扣猫。
使用非正式協(xié)議的委托模式