此份筆記紀錄如何自訂Delegate,並且使用代理人機制。
情境:當被NavigationController包著時,A ViewController要接收B ViewController所回傳的資料。B ViewController是擁有代理人機制的Controller,A ViewController要成為B ViewController的代理人。
B ViewController要成為擁有代理人機制必須有三步驟:
1. 建立自訂的Protocol
2. 建立Delegate實體變數
3. 當事件發生時,發送message給代理人
A ViewController要成為B ViewController的代理人必須有三步驟:
1. 指定代理人是誰
2. 代理人必須採納Protocol
3. 代理人必須實作method
【專案開發步驟】
建立專案:
使用Single View Application模板建立一個名為CustomDelegate的專案,使用iPhone裝置。
設計使用者介面:
替View加入NavigationController,並完成介面的設計,並將會用到的元件與對應的ViewController做連結,如下圖所示。
建立並修改B ViewController:
新增Class,並取名為DetailViewController,並與Storyboard內的ViewController做連結,如下圖所示。
<Swift>
<Object-C>
擁有代理人機制步驟1,建立自訂的Protocol。
<Swift>
在DetailViewController.swift內新增程式碼,程式碼必須撰寫在現有的Class外,如下所示。
設計使用者介面:
替View加入NavigationController,並完成介面的設計,並將會用到的元件與對應的ViewController做連結,如下圖所示。
設計使用者介面 |
新增Class,並取名為DetailViewController,並與Storyboard內的ViewController做連結,如下圖所示。
<Swift>
宣告Storyboard內的ViewController的Class是誰_Swift |
宣告Storyboard內的ViewController的Class是誰_Object-C |
擁有代理人機制步驟1,建立自訂的Protocol。
<Swift>
在DetailViewController.swift內新增程式碼,程式碼必須撰寫在現有的Class外,如下所示。
protocol DetailViewControllerDelegate {
func detailViewControllerWithName(name: NSString)
}
class DetailViewController: UIViewController {
}
<Object-C>
在DetailViewController.h內新增程式碼,程式碼必須撰寫在@interface外,如下所示。
@protocol DetailViewControllerDelegate
-(void)detailViewControllerWithName:(NSString*)name;
@end
@interface DetailViewController : UIViewController
@end
擁有代理人機制步驟2,建立Delegate實體變數,如下所示。
<Swift>
在DetailViewController.swift內新增程式碼,程式碼必須撰寫在現有的Class內,如下所示。
class DetailViewController: UIViewController {
var delegate: DetailViewControllerDelegate?
}
<Object-C>
在DetailViewController.h內新增程式碼,程式碼必須撰寫在@interface內,如下所示。
@interface DetailViewController : UIViewController
@property(nonatomic,weak)id<DetailViewControllerDelegate> delegate;
@end
擁有代理人機制步驟3,當事件發生時,傳送message給代理人。
<Swift>
在DetailViewController.swift內新增程式碼,程式碼必須撰寫在現有的Class內,如下所示。
@IBAction func click(sender: UIButton) {
navigationController.popToRootViewControllerAnimated(true)
delegate?.detailViewControllerWithName(nameField.text)
}
<Object-C>
在DetailViewController.m內新增程式碼,程式碼必須撰寫在@implemtation內,如下所示。
- (IBAction)click:(UIButton *)sender {
[self.navigationController popToRootViewControllerAnimated:YES];
[self.delegate detailViewControllerWithName:self.nameField.text];
}
修改A ViewController:
將Class名改為MainViewController,並與Storyboard內的ViewController做連結,如下圖所示。
<Swift>
宣告Storyboard內的ViewController的Class是誰_Swift |
宣告Storyboard內的ViewController的Class是誰_Object-C |
成為代理人步驟1,指定代理人是誰。
利用prepareForSegue這個method得到DetailViewController這個Class指標。
<Swift>
在MainViewController.swift內新增程式碼,程式碼必須撰寫在現有的Class內,如下所示。
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
let detailViewController: DetailViewController = segue.destinationViewController as DetailViewController
detailViewController.delegate = self
}
}
<Object-C>
在MainViewController.m內新增程式碼,程式碼必須撰寫在@implemtation內,且需#import "DetailViewController.h",如下所示。
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
DetailViewController *detailViewController = segue.destinationViewController;
detailViewController.delegate = self;
}
成為代理人步驟2,代理人必須採納Protocol。
<Swift>
在MainViewController.swift內新增程式碼,如下所示。
class MainViewController: UIViewController, DetailViewControllerDelegate {
}
<Object-C>
在MainViewController.m內新增程式碼,如下所示。
@interface MainViewController ()<DetailViewControllerDelegate>
@end
成為代理人步驟3,代理人必須實作method。
實作我們剛剛在自訂的Protocol內所宣告的method。
<Swift>
func detailViewControllerWithName(name: NSString) {
nameLabel.text = name
}
<Object-C>
-(void)detailViewControllerWithName:(NSString *)name {
self.nameLabel.text = name;
}
當DetailViewController內的Done被按下後會觸發click的function,會執行detailViewControllerWithName這個method,並會將nameField的文字傳送給Delegate。當代理人實作這個method時就會收到從DetailViewController傳過來的文字,並用name作為代表。所以我們只要把傳過來的文字顯示在我們的Label上即可。【執行結果】
【專案範例】
沒有留言:
張貼留言