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