iOS開發(fā)之協(xié)議:代理傳值
剛開始做iOS開發(fā)的時候,對 protocol、delegate 的理解一直都是暈暈乎乎一知半解的狀態(tài),不知道兩個UIViewController之間怎么進行傳值。
面試過幾個童鞋,問道怎么用 delegate 對兩個UIViewController 進行傳值的時候,回答的都是模棱兩可的。今天又有童鞋問我這個問題,所以干脆寫個blog說明一下。
1、協(xié)議(protocol),就是使用了這個協(xié)議后,必須按照協(xié)議規(guī)定的內(nèi)容來處理事情,協(xié)議中要求的方法必須實現(xiàn)(@optional的方法除外)。
protocol是一種語法,它提供了一個很方便的、實現(xiàn)delegate模式的機會。
定義protocol如下:
- @protocol ClassBDelegate<NSObject>
- - (void)methodOne;
- @optional
- - (void)methodTwo:(NSString *)value;
- @end
定義了一個ClassB的協(xié)議,這個協(xié)議中包含兩個方法,其中methodTwo為可選的。
在ClassA的頭文件(ClassA.h)中實現(xiàn)這個協(xié)議,如下代碼:
- @interface ClassA<ClassBDelegate>
- @end
在ClassA的實現(xiàn)文件(ClassA.m)中實現(xiàn)ClassBDelegate的兩個方法,其中methodTwo可以不實現(xiàn),如下:
- - (void)methodOne{
- // 具體實現(xiàn)內(nèi)容
- }
- - (void)methodTwo:(NSString *)value{
- // 具體實現(xiàn)內(nèi)容
- }
2、代理(delegate),顧名思義就是委托別人辦事,當一件事情發(fā)生后,自己不處理,讓別人來處理。
delegate和protocol沒有關(guān)系。delegate本身是一種設(shè)計模式。是把一個類自己需要做的一部分事情,讓另一個類(也可以就是自己本身)來完成。
在ClassB的頭文件(ClassB.h)中定義一個代理如下:
- @interface ClassB
- @property (nonatomic, unsafe_unretained) id<ClassBDelegate> delegate;
- @end
這樣,當我們在ClassB的實現(xiàn)文件(ClassB.m)中遇到想讓別的類(如 ClassA)處理的問題時,就可以這樣
- [self.delegate methodOne];
- [self.delegate methodTwo:@"需要傳遞的值"];
3、上邊簡單的介紹了一下協(xié)議與代理,現(xiàn)在開始講兩個UIViewController之間怎么進行傳值的事例。
首先啟動Xcode,從菜單選擇file-New Project...,彈出如下窗口:
選擇Single View Application,然后點擊 Next,彈出如下窗口:
a、給工程取個名稱為 DelegateByValue;
b、下邊的組織名稱寫自己所在的組織,這里寫的是我個人的名稱;
c、公司標識分為兩部分,com也就是Company(公司)的意思,iostour寫自己所在的公司名稱,這里我寫的是iOS之旅的iostour;
d、類前綴,這個可以隨便,不過我這里寫的是W,因為我姓衛(wèi),所以取其首字母,這樣公司同事一看到這個類就知道是我寫的;
e、設(shè)備選擇iPhone;
f、我們用xib的方式編寫,故此處不勾選;
g、使用ARC機制,勾選;
h、該事例不做單元測試,不勾選。
然后單擊 Next,彈出如下窗口:
選擇一個存儲工程的目錄,然后單擊 Create創(chuàng)建一個工程,創(chuàng)建完成后的目錄結(jié)構(gòu)如下:
接下來我們需要在兩個Controller之間進行傳值,由于創(chuàng)建工程的時候已經(jīng)自動為我們生成了一個WViewController,所以我們只需要在創(chuàng)建一個就Controller就好啦。
鼠標右鍵DelegateByValue,點擊New File... 如下:
然后彈出如下窗口
選擇iOS>Cocoa Touch >Objective-C Class,然后單擊 Next,彈出如下窗口:
然后,取名為WTwoViewController,單擊 Next,選擇存儲目錄,然后Create。
接下來為WTowViewController 創(chuàng)建一個.xib文件,步驟以此如下:
a、鼠標右鍵DelegateByValue,點擊New File...
b、然后彈出如下窗口:
這次我們選擇iOS > User Interface > View,單擊 Next,取名為WTwoViewController,然后Create。
創(chuàng)建好WTwoViewController后,我們讓WTwoViewController.xib與WTwoViewController.h關(guān)聯(lián)起來,如下圖:
按照上圖1、2、3的步驟依次進行,選中1,點擊2,設(shè)置3 Class為WTwoViewController,然后回車,然后如下圖:
點擊4、按住5 view后邊的空心圓,拖動到6 view上,然后松手及
接下來給view上拖一個UITextField和一個UIButton,并給UITextField起名為txtValue,給UIButton設(shè)置一個Action,起名為pressChange
步驟如下:
1、分屏顯示xib與代碼,
2、選擇UITextField,并按住control鍵, 拖動到右側(cè)的代碼(WTwoViewController.h)區(qū)域,會彈出如下窗口:
為其設(shè)置名稱,然后點擊Connect;
3、同樣,選擇UIButton,并按住control鍵,拖動到右側(cè)代碼(WTwoViewController.h)區(qū)域,會彈出如下窗口:
這次因為是要給UIButton設(shè)置點擊事件,所以改變1 Connection為Action,然后設(shè)置名稱,點擊Connect。
至此WTwoViewController的窗口視圖以設(shè)置完成。
同樣步驟設(shè)置WViewController.xib窗口。
給 view 上拖一個UILabel和一個UIButton,并給UILabel起名為lblValue,給UIButton設(shè)置一個Action,起名為pressCasting。
至此窗口設(shè)置部分已經(jīng)全部完成。
接下來在WTwoViewController.h中定義一個協(xié)議,WTwoViewControllerDelegate,并給WTwoViewController定義一個代理,代碼如下:
- //
- // WTwoViewController.h
- // DelegateByValue
- //
- // Created by wzrong on 13-7-20.
- // Copyright (c) 2013年 wzrong. All rights reserved.
- //
- #import <UIKit/UIKit.h>
- @protocol WTwoViewControllerDelegate <NSObject>
- - (void)changeValue:(NSString *)value;
- @end
- @interface WTwoViewController : UIViewController
- @property (nonatomic, unsafe_unretained) id<WTwoViewControllerDelegate> delegate;
- @property (nonatomic, strong) IBOutlet UITextField *txtValue;
- - (IBAction)pressChange:(id)sender;
- @end
接下來在WTwoViewController.m中的 - (IBAction)pressChange:(id)sender 方法中把代理派發(fā)出去,順便把窗口給銷毀,代碼如下:
- - (IBAction)pressChange:(id)sender {
- [self.delegate changeValue:self.txtValue.text];
- [self dismissViewControllerAnimated:YES completion:nil];
- }
WTwoViewController中的設(shè)置已經(jīng)完成,接下要在WViewController中調(diào)用WTwoViewController,并實現(xiàn)WTwoViewControllerDelegate代碼。
首先在WViewController.h中實現(xiàn)代理,代碼如下:
- //
- // WViewController.h
- // DelegateByValue
- //
- // Created by wzrong on 13-7-20.
- // Copyright (c) 2013年 wzrong. All rights reserved.
- //
- #import <UIKit/UIKit.h>
- #import "WTwoViewController.h"
- @interface WViewController : UIViewController<WTwoViewControllerDelegate>
- @property (strong, nonatomic) IBOutlet UILabel *lblValue;
- - (IBAction)pressCasting:(id)sender;
- @end
其在WViewController.m的 - (IBAction)pressCasting:(id)sender 方法中調(diào)用WTwoViewController,并設(shè)置代理的回調(diào)方法,代碼如下:
- - (IBAction)pressCasting:(id)sender {
- WTwoViewController *controller = [[WTwoViewController alloc]initWithNibName:@"WTwoViewController" bundle:nil];
- controller.delegate = self;
- [self presentViewController:controller animated:YES completion:nil];
- }
- - (void)changeValue:(NSString *)value{
- // 改變UILabel的值
- self.lblValue.text = value;
- }
OK,搞定。
這里只實現(xiàn)了從WTwoViewController到WViewController的傳值,大家可以自己做做從WViewController到WTwoViewController的傳值。
工程源碼傳送門DelegateByValue