擴(kuò)展(Extension)
一般用擴(kuò)展來做什么?
1.聲明私有屬性
,是可以不對子類暴露的。
2.聲明私有方法
,方便閱讀。
3.聲明私有成員變量
析命。
擴(kuò)展的特點(diǎn):
1.編譯時(shí)
決議。
2.只以聲明的形式存在
,沒有具體實(shí)現(xiàn),多數(shù)情況寄生于宿主類的.m中,也就是說,它不是獨(dú)立存在實(shí)現(xiàn)的一個(gè)文件逃默,可以把擴(kuò)展理解為類的一個(gè)內(nèi)部的私有聲明鹃愤。
3.不能為系統(tǒng)類添加擴(kuò)展。
分類和擴(kuò)展的區(qū)別:
1.分類是運(yùn)行時(shí)決議,擴(kuò)展是編譯時(shí)決議笑旺。
2.分類可以有聲明有實(shí)現(xiàn),而擴(kuò)展只有聲明,它的實(shí)現(xiàn)是直接寫在宿主類當(dāng)中。
3.可以為系統(tǒng)類添加分類,但不能為系統(tǒng)類添加擴(kuò)展馍资。
代理(Delegate):
什么是代理:
1.準(zhǔn)確的說是一種軟件設(shè)計(jì)模式筒主,代理模式.
2.iOS當(dāng)中以@protocol形式體現(xiàn).
3.傳遞方式是一對一.
代理的工作流程:
1.委托方會(huì)要求代理放需要實(shí)現(xiàn)的接口,全部定義在協(xié)議當(dāng)中鸟蟹。
2.在協(xié)議當(dāng)中可以聲明屬性乌妙,也可以聲明方法。
3.代理會(huì)按照協(xié)議實(shí)現(xiàn)方法建钥。
4.代理會(huì)返回一個(gè)處理結(jié)果給委托方藤韵。
5.委托方需要調(diào)用代理方遵從的協(xié)議方法。
首先定義一個(gè)協(xié)議類熊经,來定義公共協(xié)議
#import <Foundation/Foundation.h>
@protocol LoginProtocol <NSObject>
@optional
- (void)userLoginWithUsername:(NSString *)username password:(NSString *)password;
@end
定義委托類泽艘,這里簡單實(shí)現(xiàn)了一個(gè)用戶登錄功能欲险,將用戶登錄后的賬號(hào)密碼傳遞出去,由代理來處理具體登錄細(xì)節(jié)匹涮。
#import <UIKit/UIKit.h>
#import "LoginProtocol.h"
/**
* 當(dāng)前類是委托類天试。用戶登錄后,讓代理對象去實(shí)現(xiàn)登錄的具體細(xì)節(jié)然低,委托類不需要知道其中實(shí)現(xiàn)的具體細(xì)節(jié)喜每。
*/
@interface LoginViewController : UIViewController
// 通過屬性來設(shè)置代理對象
@property (nonatomic, weak) id<LoginProtocol> delegate;
@end
實(shí)現(xiàn)部分:
@implementation LoginViewController
- (void)loginButtonClick:(UIButton *)button {
// 判斷代理對象是否實(shí)現(xiàn)這個(gè)方法,沒有實(shí)現(xiàn)會(huì)導(dǎo)致崩潰
if ([self.delegate respondsToSelector:@selector(userLoginWithUsername:password:)]) {
// 調(diào)用代理對象的登錄方法雳攘,代理對象去實(shí)現(xiàn)登錄方法
[self.delegate userLoginWithUsername:self.username.text password:self.password.text];
}
}
代理方带兜,實(shí)現(xiàn)具體的登錄流程,委托方不需要知道實(shí)現(xiàn)細(xì)節(jié)吨灭。
// 遵守登錄協(xié)議
@interface ViewController () <LoginProtocol>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
LoginViewController *loginVC = [[LoginViewController alloc] init];
loginVC.delegate = self;
[self.navigationController pushViewController:loginVC animated:YES];
}
/**
* 代理方實(shí)現(xiàn)具體登錄細(xì)節(jié)
*/
- (void)userLoginWithUsername:(NSString *)username password:(NSString *)password {
NSLog(@"username : %@, password : %@", username, password);
}
這里我們需要知道一下刚照,協(xié)議中可以定義哪些內(nèi)容?協(xié)議可以通過@required定義必須實(shí)現(xiàn)的代理方法沃于,通過@optional定義可選方法涩咖。
在我們實(shí)際開發(fā)中,委托方和代理方的關(guān)系應(yīng)該怎么樣建立繁莹,他們建立的關(guān)系的過程中檩互,應(yīng)該注意哪些問題?
在使用代理的時(shí)候咨演,存在一個(gè)循環(huán)引用的問題
闸昨,當(dāng)代理,協(xié)議薄风,委托都通過強(qiáng)引用(strong)形成一個(gè)閉環(huán)饵较,則會(huì)造成內(nèi)存泄露的問題,此時(shí)我們通常會(huì)讓委托方弱(weak)引用指向代理方來避免循環(huán)引用遭赂。
通知(NSNotification)
- 使用觀察者模式來實(shí)現(xiàn)的循诉、用于跨層傳遞消息的機(jī)制(一般數(shù)據(jù)處理邏輯是網(wǎng)絡(luò)層傳遞到數(shù)據(jù)層,然后在經(jīng)過業(yè)務(wù)邏輯層加工再去更新UI撇他。如果有時(shí)候網(wǎng)絡(luò)層返回的數(shù)據(jù)不經(jīng)過業(yè)務(wù)邏輯層茄猫,直接到達(dá)UI層,這時(shí)候就用到跨層傳遞)困肩。
- 傳遞方式為一對多划纽。
通知和代理的區(qū)別:
- 通知是觀察者模式來實(shí)現(xiàn),代理是由代理模式實(shí)現(xiàn)的锌畸。
- 通知傳遞方式是一對多勇劣。代理是傳遞方式是一對一。
如何實(shí)現(xiàn)通知機(jī)制潭枣?
首先比默,信息的傳遞就依靠通知(NSNotification)幻捏,也就是說,通知就是信息(執(zhí)行的方法退敦,觀察者本身(self),參數(shù))的包裝粘咖。通知中心(NSNotificationCenter)是個(gè)單例,向通知中心注冊觀察者侈百,也就是說瓮下,這個(gè)通知中心有個(gè)集合,這個(gè)集合存放著觀察者钝域。
那么這個(gè)集合是什么樣的數(shù)據(jù)類型 讽坏? 大概猜想: 發(fā)送通知需要name參數(shù),添加觀察者也有個(gè)name參數(shù)例证,這兩個(gè)name一樣的時(shí)候路呜,當(dāng)發(fā)送通知時(shí)候,觀察者對象就能接受到信息织咧,執(zhí)行對應(yīng)的操作胀葱。猜想這個(gè)集合是NSDictionary
。
key就是name笙蒙,value就是NSArray(存放數(shù)據(jù)模型)抵屿,里面存放觀察者對象。如下圖