protocol(協(xié)議)是一組公開接口的集合荣恐,任何類都可以實現這一組接口春贸。
協(xié)議的聲明
@protocol testProtocol
@required
- (void)requiredMethod;
@optional
- (BOOL)optionalMethod;
@end
在objective-c中待秃,我們通過@protocol關鍵字來聲明一個協(xié)議居触,在協(xié)議中我們可以聲明需要的方法提供給遵守協(xié)議的類妖混。協(xié)議中的方法有2種類型如下:
- @required :遵守該協(xié)議的類必須實現此關鍵字下的所有方法。
- @optional :遵守該協(xié)議的類可以選擇實現此關鍵字下的方法轮洋,也可以都不實現制市。默認情況下協(xié)議中的方法都是這種類型的。
遵循一個協(xié)議
在聲明后面添加尖括號<協(xié)議名>來讓某個類遵循某個協(xié)議
@interface ClassA : NSObject<testProtocol>
@end
協(xié)議的特點
協(xié)議的應用
1.約束對象
在開發(fā)中弊予,我們經常會遇到這樣一種情況祥楣,我們希望使用到的實例對象必須擁有一些功能。這個時候我們可以要求這個實例對象的類必須遵守指定的協(xié)議。
//定義一個協(xié)議
@protocol isProtocol
@required
-(void)printSome;
@end
@interface ViewController ()
//需要一個遵循了isProtocol協(xié)議的對象
@property (nonatomic, strong) id<isProtocol> obj;
@end
這樣寫的好處在于增加了代碼的可讀性误褪,讓開發(fā)人員一眼就明白這個對象需要滿足什么條件责鳍。然后我們定義一個類,這個類遵循isProtocol這個協(xié)議兽间,并實現協(xié)議中的方法
@interface ClassA : NSObject<isProtocol>
@end
@implementation ClassA
- (void)printSome {
NSLog(@"do protocol method");
}
@end
在viewController中調用
self.obj = [[ClassA alloc] init];
[self.obj printSome]
2.多重繼承
面向對象編程語言中的多重繼承指的是一個類可以同時繼承多個父類的行為和特征功能历葛。單一繼承是指:一個子類只繼承一個父類。
從上面的例子我們可以看出嘀略,遵從了協(xié)議的對象可以調用協(xié)議中提供的方法恤溶,不需要知道對象的具體類型。也就是說只要是遵從了協(xié)議的類都可以對協(xié)議中提供的方法進行不同的實現帜羊。并且一個類可以遵守多個協(xié)議宏娄!
例如,人類只能奔跑逮壁,是不能飛行和游泳的。但我們希望人類可以繼承鳥和魚的特性粮宛,讓人類也可以飛行和游泳窥淆。
//定義鳥和魚的協(xié)議
@protocol birdProtocol
@required
-(void)canFlying;
@end
@protocol fishProtocol
@required
-(void)canSwiming;
@end
//定義人的類,讓人類遵循鳥和魚這兩個協(xié)議
@interface Person : NSObject<birdProtocol, fishProtocol>
//人本身只會奔跑
- (void)canRunning;
@end
但遵循鳥和魚的協(xié)議后巍杈,人就可以實現鳥和魚協(xié)議中提供的方法忧饭,擁有飛翔和游泳的能力。
@implementation Person
- (void)canRunning {
NSLog(@"i can running");
}
- (void)canFlying {
NSLog(@"i can fly");
}
- (void)canSwiming {
NSLog(@"i can swim");
}
@end
//這樣的人就可以同時擁有自己和其他協(xié)議提供的能力了筷畦。
Person *person = [[Person alloc] init];
[person canRunning];
[person canFlying];
[person canSwiming];
3.代理词裤,傳值
代理模式的定義:為其他對象提供一種代理以控制對這個對象的訪問。在某些情況下鳖宾,一個對象不適合或者不能直接引用另一個對象吼砂,而代理對象可以在客戶端和目標對象之間起到中介的作用。
在開發(fā)中鼎文,我們可能遇到這樣一種情況渔肩,某個類的實例希望實現一個功能,但這個功能和這個實例并沒有什么關系拇惋。這個時候就需要委托一個具有相關職能的類的實例來代理實現這個工作周偎,并可以把功能中得到的結果告訴自己。
例如:一個老板想開店賺錢撑帖,但老板并不應該親自洗完蓉坎,收錢。所以老板需要請一個會洗完和收銀的員工來幫他工作胡嘿。
@protocol employeesProtocol
//洗碗
- (void)Washing;
//收銀
- (NSInteger)Cashier;
@end
首先我們需要一個協(xié)議來限制員工必須會洗完和收銀蛉艾。
@interface Employees : NSObject<employeesProtocol>
@end
@implementation Employees
-(void)Washing {
NSLog(@"working");
}
-(NSInteger)Cashier {
return 100;
}
@end
@interface Boss : NSObject
@property (nonatomic, strong) id<employeesProtocol> employee;
@property (nonatomic, assign) NSInteger assets;
- (void)letEmployeeWorking;
@end
@implementation Boss
- (void)letEmployeeWorking {
[self.employee Washing];
self.assets += [self.employee Cashier];
}
@end
定義員工類,遵循員工協(xié)議。并實現協(xié)議中提供的方法伺通。定義老板類箍土,包含一個遵循員工協(xié)議的對象和一個變量表示當前的資產拉讯。老板可以讓員工工作蹲坷,員工洗完媚创,收銀并把賺來的錢交給老板
id<employeesProtocol> employee = [[Employees alloc] init];
Boss *boss = [[Boss alloc] init];
boss.delegate = employee;
[boss letEmployeeWorking];
使用的時候明棍,我們只需要設置boss的代理戒洼,并且開始干活就可以了堪簿。于是每當boss讓員工干活就會觸發(fā)員工協(xié)議中的方法驻售〗槠溃可以參考tableview的點擊操作矢空,每當tableview點擊以后航罗,就會通知代理,我被點擊了你可以開始處理這個事件了屁药。
4.回調
回調是建立在代理之上的粥血,當我們想把事件或數據回調給某個對象,我們可以把這個對象設置為自己的代理酿箭。這樣我們就可以通過調用協(xié)議提供的方法把事件或數據傳遞給代理了复亏。
最簡單的例子:我們有A,B兩個viewcontroller缭嫡,A->B缔御,當B加載后將這個信息告訴A。
@protocol callbackProtocol <NSObject>
- (void)callBackWith:(NSString *)msg;
@end
@interface NextViewController : UIViewController
@property (nonatomic, weak) id<callbackProtocol> delegate;
@end
@implementation NextViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.delegate callBackWith:@"viewDidLoad"];
}
@end
先定義B控制器妇蛀,B控制器提供一個回調協(xié)議耕突,并包含一個遵循這個回調協(xié)議的代理對象,當load時评架,執(zhí)行代理提供的方法眷茁。
@interface ViewController ()<callbackProtocol>
@end
//實現協(xié)議中的方法
- (void)callBackWith:(NSString *)msg {
NSLog(@"%@",msg);
}
NextViewController *vc = [[NextViewController alloc] init];
vc.delegate = self;
[self.navigationController pushViewController:vc animated:YES];
而界面A遵循B中的回調協(xié)議,初始化控制器B纵诞,并設置自己為B中的代理對象蔼卡。這樣當B執(zhí)行viewdidload的時候就會執(zhí)行代理,告訴A控制器自己正在viewDidLoad挣磨。即把初始化這個事件和信息回調給A控制器了雇逞。