代理:
這裡只強調一些注意點:
注意點(一):代理為什麼要用weak修飾?
答:為了防止記憶體洩漏
程式碼如下:
HSDog.h類 @protocol HSDogDelegate <NSObject> @end @interface HSDog : NSObject @property (nonatomic, weak) id<HSDogDelegate>delegate; @end HSDog.m #import "HSDog.h" @implementation HSDog - (void)dealloc { NSLog(@"HSDog----銷燬"); } @end HSPerson.h @interface HSPerson : NSObject @end HSPerson.m #import "HSPerson.h" #import "HSDog.h" @interface HSPerson()<HSDogDelegate> /** 強引用dog*/ @property (nonatomic, strong) HSDog *dog; @end @implementation HSPerson - (instancetype)init { self = [super init]; if (self) { // 例項化dog self.dog = [[HSDog alloc] init]; self.dog.delegate = self; } return self; } - (void)dealloc { NSLog(@"HSPerson----銷燬"); } @end ViewController.m #import "ViewController.h" #import "HSPerson.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; HSPerson *person = [[HSPerson alloc] init]; } @end
程式碼其實可以不用看,只需要知道幾點:
(1)Person *p = [Person alloc]init];在ARC中預設是強指標指向,但p指標存放在棧區,出了其所在的括號就會被回收掉
(2)self.dog = [[Dog alloc]init];注意的是:self.dog呼叫set方法,方法內部其實是:__strong Dog* _dog; 因為有:
/** 強引用dog*/ @property (nonatomic, strong) HSDog *dog;
所以知道_dog是strong修飾的.
(3)而dog是依附於person物件的,也就是說self.dog指標的存亡取決於person物件是否消失,如果person物件沒有消失,那麼self.dog就一直存在著。
同理self.dog.delegate= self也是如此
綜上所述:代理需要用weak修飾,至於用strong會不會產生記憶體洩漏也要根據具體程式碼和指標指向來判斷。
1.需要掌握:
第一個最簡單的通知的使用:過程分析:
注意點:新增監聽者必須寫在傳送通知之前
1.通知中心傳送通知,(前提是必須有一個通知,可以直接在傳送通知中寫出來,不用提前建立通知物件).
2.通知中心傳送了通知之後,會找前面是否有監聽者監聽我的這個通知,如果有,就會找到這個監聽者物件.
3.找到監聽者物件後會呼叫監聽者物件的方法,完成實現通知的方法.
4.注意:不能忘記通知的使用完畢後,要移除監聽者.
5.注意:有沒有想過:為什麼一般我寫監聽者物件實現的方法中帶的引數是通知型別的?可以帶別的型別的引數麼?
答:是不能帶別的型別的引數的,該方法存在的意義在於:我傳給監聽者一個通知,並要你實現一個方法,目的是為了讓你看到
我通知的具體內容,因為我傳遞的就是通知,該方法也稱之為通知方法,用於傳遞通知的具體資訊,怎麼看呢,只需要帶上通知型別的引數列印出來就可以了.
#import <Foundation/Foundation.h> @interface News : NSObject @property (nonatomic,copy) NSString *newsName; @end
News.m
#import "News.h" @implementation News @end
Person.h
#import <Foundation/Foundation.h> @interface Person : NSObject @property (nonatomic,copy) NSString *name; - (void)show:(NSNotification *)notification; @end
Person.m
#import "Person.h" @implementation Person - (void)show:(NSNotification *)notification{ NSDictionary *dict = notification.userInfo; NSLog(@"%@",dict[@"吳亦凡"]); NSLog(@"監聽到通知了 監聽人 %@--- %@",self.name,notification); } - (void)dealloc{ #pragma mark -- 移除監聽者 // 在MRC中,非ARC 中,需要呼叫下面的方法 // [super dealloc]; // NSLog(@"移除監聽者"); [[NSNotificationCenter defaultCenter]removeObserver:self]; } @end
main.m
// // main.m // 03-通知的使用 // // Created by apple on 16/7/15. // Copyright © 2016年 itcast. All rights reserved. // #import <Foundation/Foundation.h> #import "News.h" #import "Person.h" int main(int argc, const char * argv[]) { @autoreleasepool { News *sinaNew = [[News alloc]init]; sinaNew.newsName = @"sina"; News *wangNew = [[News alloc]init]; wangNew.newsName = @"wangyi"; Person *p1 = [[Person alloc]init]; p1.name = @"zhangsan"; Person *p2 = [[Person alloc]init]; p2.name = @"lisi"; #pragma mark -- 通知 // 1. 引數1: name =>通知的名字 // 2. 引數2: object =>釋出通知的物件 // 3. 引數3: userInfo=>額外資訊 NSNotification *notification = [NSNotification notificationWithName:@"yule" object:sinaNew userInfo:@{@"趙薇事件":@"黑社會"}]; NSNotification *notification2 = [NSNotification notificationWithName:@"yule" object:wangNew userInfo:@{@"吳亦凡":@"做壞事"}]; NSNotification *notification3 = [NSNotification notificationWithName:@"junshi" object:sinaNew userInfo:@{@"南海":@"仲裁不通過"}]; #pragma mark -- 釋出通知 //1. 現有通知中心 // 通知中心 是單例設定模式, 它有一個預設的方法,可以得到這個物件[NSNotificationCenter defaultCenter] NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; //2. 釋出通知 // 將建立的通知釋出出去 // [notificationCenter postNotification:notification]; #pragma mark -- 監聽通知 //新增監聽者 //<#(nonnull id)#> 代表監聽者物件 //@selector 代表監聽到訊息後,所呼叫的方法 // name 釋出的通知名字 傳入nil代表無論是什麼通知,都接受 //object 釋出通知的物件 傳入nil代表無論哪個通知物件釋出的資訊都接受 [notificationCenter addObserver:p1 selector:@selector(show:) name:nil object:nil]; [notificationCenter addObserver:p2 selector:@selector(show:) name:@"yule" object:nil]; [notificationCenter postNotification:notification]; [notificationCenter postNotification:notification2]; [notificationCenter postNotification:notification3]; NSLog(@"程式碼執行結束"); } return 0; }
代理事例二:
main.m
// // main.m // 01-通知的使用 // // Created by apple on 16/7/17. // Copyright © 2016年 itcast. All rights reserved. // #import <Foundation/Foundation.h> #import "Baby.h" #import "Father.h" #import "Mother.h" int main(int argc, const char * argv[]) { @autoreleasepool { Father *father = [[ Father alloc]init]; Mother *mother = [[Mother alloc]init]; Baby *baby = [[Baby alloc]init]; // 通知的使用: 新增監聽者 // 第一個引數 id--> 監聽者物件 // 第二個引數 selector--> 監聽到後呼叫的方法 // 第三個引數 name --> 釋出通知的名字 // 第四個引數 object -> 釋出通知的物件 [[NSNotificationCenter defaultCenter]addObserver:father selector:@selector(notification:) name:nil object:baby]; [[NSNotificationCenter defaultCenter]addObserver:mother selector:@selector(notification:) name:nil object:baby]; [baby babyKu]; [baby babyNiao]; } return 0; }
Baby.h
// // Baby.h // 01-通知的使用 // // Created by apple on 16/7/17. // Copyright © 2016年 itcast. All rights reserved. // #import <Foundation/Foundation.h> @class Baby; @interface Baby : NSObject -(void)babyKu; - (void)babyNiao; @end
Baby.m
// // Baby.m // 01-通知的使用 // // Created by apple on 16/7/17. // Copyright © 2016年 itcast. All rights reserved. // #import "Baby.h" @implementation Baby -(void)babyKu{ NSLog(@"寶寶在哭"); //1. 通知的使用 // NSNotification //1.1 釋出通知 // name---> 通知的名字 // object -->釋出通知的物件 // userInfo-->額外資訊 [[NSNotificationCenter defaultCenter]postNotificationName:@"ku" object:self userInfo:nil]; } - (void)babyNiao{ NSLog(@"寶寶尿床了"); [[NSNotificationCenter defaultCenter]postNotificationName:@"niao" object:self userInfo:nil]; } @end
Father.h
// // Father.h // 01-通知的使用 // // Created by apple on 16/7/17. // Copyright © 2016年 itcast. All rights reserved. // #import <Foundation/Foundation.h> @interface Father : NSObject @end
Father.m
// // Father.m // 01-通知的使用 // // Created by apple on 16/7/17. // Copyright © 2016年 itcast. All rights reserved. // #import "Father.h" @interface Father () @end @implementation Father - (void)notification:(NSNotification *)notification{ NSLog(@"%@",notification); NSString *name = notification.name; if ([@"ku" isEqualToString:name]) { [self lookBabyKu]; }else{ [self lookBabyNiao]; } } - (void)dealloc{ //銷燬監聽者 [[NSNotificationCenter defaultCenter]removeObserver:self]; } - (void)lookBabyKu{ NSLog(@"爸爸 照顧嬰兒哭"); } - (void)lookBabyNiao{ NSLog(@"爸爸 照顧嬰兒尿"); } @end
小結:
//傳送通知 [[NSNotificationCenter defaultCenter] postNotificationName:@"TZ" object:self userInfo:nil];
第二步:哪個控制器需要監聽我這個通知,我就在那個控制器裡面(具體位置是可以獲取到目標控制器的方法中),新增監聽者物件
//用通知來傳遞資料 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cancelLoginMessage) name:nil object:listController];
第三步:實現第二步裡面的方法
#pragma mark -- 實現通知方法 - (void)cancelLoginMessage{ //使用者名稱和密碼清空 _nameField.text = @""; _passwordField.text = @""; //關閉自動登入和記住密碼switch _recordSwitch.on = NO; _autoSwitch.on = NO; //登入按鈕 _loginBtn.enabled = NO; //儲存在使用者偏好設定的資料也要恢復預設值 [[NSUserDefaults standardUserDefaults] setBool:NO forKey:KRecordSwitch]; [[NSUserDefaults standardUserDefaults] setBool:NO forKey:KAutoSwitch]; [[NSUserDefaults standardUserDefaults] setObject:@"" forKey:KUserName]; [[NSUserDefaults standardUserDefaults] setObject:@"" forKey:KPassWord]; }
第四步:很關鍵,別忘了在這個下面移除監聽者
#pragma mark -- 銷燬監聽者 - (void)dealloc{ [[NSNotificationCenter defaultCenter] removeObserver:self]; }