剛開始做iOS開發的時候,對 protocol、delegate 的理解一直都是暈暈乎乎一知半解的狀態,不知道兩個UIViewController之間怎麼進行傳值。
面試過幾個童鞋,問道怎麼用 delegate 對 兩個 UIViewController 進行傳值的時候,回答的都是模稜兩可的。今天又有童鞋問我這個問題,所以乾脆寫個blog說明一下。
1、協議(protocol),就是使用了這個協議後,必須按照協議規定的內容來處理事情,協議中要求的方法必須實現(@optional的方法除外)。
protocol是一種文法,它提供了一個很方便的、實現delegate模式的機會。
定義protocol
@protocol ClassBDelegate<NSObject>
- (void)methodOne;
@optional
- (void)methodTwo:(NSString *)value;
@end
定義了一個ClassB的協議,這個協議中包含兩個方法,其中methodTwo為可選的。
在ClassA的標頭檔(ClassA.h)中實現這個協議,
@interface ClassA<ClassBDelegate>
@end
在ClassA的實現檔案(ClassA.m)中實現ClassBDelegate的兩個方法,其中methodTwo可以不實現
- (void)methodOne{
// 具體實現內容
}
- (void)methodTwo:(NSString *)value{
// 具體實現內容
}
2、代理(delegate),顧名思義就是委託別人辦事,當一件事情發生後,自己不處理,讓別人來處理。
delegate和protocol沒有關係。delegate本身是一種設計模式。是把一個類自己需要做的一部分事情,讓另一個類(也可以就是自己本身)來完成。
在ClassB的標頭檔(ClassB.h)中定義一個代理
@interface ClassB
@property (nonatomic, unsafe_unretained) id<ClassBDelegate> delegate;
@end
這樣,當我們在ClassB的實現檔案(ClassB.m)中遇到想讓別的類(如 ClassA)處理的問題時,就可以這樣
[self.delegate methodOne];
[self.delegate methodTwo:@"需要傳遞的值"];3、上邊簡單的介紹了一下協議與代理,現在開始講兩個UIViewController之間怎麼進行傳值的案例。
首先啟動Xcode,從菜單選擇file-New Project...,
選擇Single View Application,然後點擊 Next,
a、給工程取個名稱為 DelegateByValue;
b、下邊的組織名稱寫自己所在的組織,這裡寫的是我個人的名稱;
c、公司標識分為兩部分,com也就是Company(公司)的意思,iostour寫自己所在的公司名稱,這裡我寫的是iOS之旅的iostour;
d、類首碼,這個可以隨便,不過我這裡寫的是W,因為我姓衛,所以取其首字母,這樣公司同事一看到這個類就知道是我寫的;
e、裝置選擇iPhone;
f、我們用xib的方式編寫,故此處不勾選;
g、使用ARC機制,勾選;
h、該案例不做單元測試,不勾選。
然後單擊 Next,
選擇一個儲存工程的目錄,然後單擊 Create建立一個工程,建立完成後的目錄結構
接下來我們需要在兩個Controller之間進行傳值,由於建立工程的時候已經自動為我們產生了一個WViewController,所以我們只需要在建立一個就Controller就好啦。
滑鼠右鍵DelegateByValue,點擊New File...
選擇iOS>Cocoa Touch >Objective-C Class,然後單擊 Next,
然後,取名為WTwoViewController,單擊 Next,選擇儲存目錄,然後Create。
接下來為WTowViewController 建立一個.xib檔案,步驟以此如下:
a、滑鼠右鍵DelegateByValue,點擊New File...
b、然後彈出如下視窗:
這次我們選擇iOS > User Interface > View,單擊 Next,取名為WTwoViewController,然後Create。
建立好WTwoViewController後,我們讓WTwoViewController.xib與WTwoViewController.h關聯起來,
按照1、2、3的步驟依次進行,選中1,點擊2,設定3 Class為WTwoViewController,然後斷行符號,
點擊4、按住5 view後邊的空心圓,拖動到6 view上,然後鬆手及
接下來給view上拖一個UITextField和一個UIButton,並給UITextField起名為txtValue,給UIButton設定一個Action,起名為pressChange
步驟如下:
1、分屏顯示xib與代碼,
2、選擇UITextField,並按住control鍵, 拖動到右側的代碼(WTwoViewController.h)地區,會彈出如下視窗:
為其設定名稱,然後點擊Connect;
3、同樣,選擇UIButton,並按住control鍵,拖動到右側代碼(WTwoViewController.h)地區,會彈出如下視窗:
這次因為是要給UIButton設定點擊事件,所以改變1 Connection為Action,然後設定名稱,點擊Connect。
至此WTwoViewController的視窗視圖以設定完成。
同樣步驟設定WViewController.xib視窗。
給 view 上拖一個UILabel和一個UIButton,並給UILabel起名為lblValue,給UIButton設定一個Action,起名為pressCasting。
接下來在WTwoViewController.h中定義一個協議,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 方法中把代理派發出去,順便把視窗給銷毀,代碼如下:
- (IBAction)pressChange:(id)sender {
[self.delegate changeValue:self.txtValue.text];
[self dismissViewControllerAnimated:YES completion:nil];
}
WTwoViewController中的設定已經完成,接下要在WViewController中調用WTwoViewController,並實現WTwoViewControllerDelegate代碼。
首先在WViewController.h中實現代理,代碼如下:
//
// 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 方法中調用WTwoViewController,並設定代理的回調方法,代碼如下:
- (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,搞定。
這裡只實現了從WTwoViewController到WViewController的傳值,大家可以自己做做從WViewController到WTwoViewController的傳值。
工程源碼傳送門DelegateByValue