在日常開發(fā)過程中机断,我們經常會遇到值傳遞畸颅。這里盟猖,介紹幾種iOS開發(fā)中常見的傳值方式讨衣。
1.屬性傳值
屬性傳值是iOS中最為常見的正向傳值方式,假定我們現在有這樣一個需求式镐,在A控制器點擊按鈕反镇,將按鈕的標題顯示在B控制器的label上。首先娘汞,我們創(chuàng)建兩個控制器CCFirstViewController和CCSecondViewController,在CCSecondViewController.h中聲明一個屬性
@interface CCSecondViewController : UIViewController
@property (nonatomic, strong) NSString *buttonTitleString;
@end
@interface CCSecondViewController
@end
@implementation CCSecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 30)];
label.center = self.view.center;
label.text = self.buttonTitleString;
[self.view addSubview:label];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self dismissViewControllerAnimated:YES completion:nil];
}
@end
現在歹茶,在第二個控制器中已經有了接收按鈕標題的屬性,接下來,在第一個控制器中添加一個按鈕惊豺,點擊按鈕讓第一個控制器將按鈕標題傳遞給第二個控制器燎孟。
@interface CCFirstViewController ()
@end
@implementation CCFirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.frame = CGRectMake(0, 0, 100, 30);
button.center = self.view.center;
[button setTitle:@"浪漫戀星空" forState:UIControlStateNormal];
[button addTarget:self action:@selector(handleButtonEvent:) forControlEvents:UIControlEventTouchDragInside];
[self.view addSubview:button];
}
- (void)handleButtonEvent:(UIButton *)sender {
CCSecondViewController *vc = [[CCSecondViewController alloc] init];
vc.buttonTitleString = sender.currentTitle;
[self presentViewController:vc animated:YES completion:nil];
}
@end
運行程序,點擊第一個控制器的按鈕跳轉到第二個控制器尸昧,我們會發(fā)現第二個控制器的label已經有值了揩页。這就是屬性傳值的簡單應用。
屬性傳值的基本步驟就是在需要接收值的控制器公開一個屬性烹俗,在前一個控制器跳轉的事件中初始化接收值的控制器爆侣,將需要傳遞的值賦值給接收值的控制器公開的屬性,接下來做控制器的跳轉幢妄。
2.代理傳值
在日常的開發(fā)中兔仰,我們遇到的值傳遞不可能只是簡單的正向傳遞,很多時候我們也需要將第二個控制器中的值傳遞給前一個控制器蕉鸳,這就是常見的反向傳值乎赴。屬性傳值已經不能滿足我們的需求了,就需要用到第二種常見的傳值方式置吓,代理傳值和二。同樣假定一個需求他爸,在B控制器點擊按鈕涨醋,將按鈕的標題顯示在A控制器的label上功蜓。還是用上述兩個創(chuàng)建好的控制器完成。
簡單的將第一個控制器中的label和第二個控制器中的button創(chuàng)建好戴质,為了方便度宦,這里將第一個控制器的跳轉事件直接寫到touch事件里面(感覺有哪里沒對)。接下來告匠,我們需要做的是點擊第二個控制器中的按鈕戈抄,將按鈕的標題傳回第一個控制器。
首先后专,在需要傳值出去的控制器划鸽,也就是我們的第二個控制器的.h文件中,聲明一個協(xié)議戚哎,并且聲明一個傳值需要的協(xié)議方法裸诽。
// 聲明協(xié)議以及傳值的方法
@protocol CCSecondViewControllerDelegate <NSObject>
- (void)sendButtonTitleToFirst:(NSString *)string;
@end
接下來,聲明一個代理屬性型凳。
@interface CCSecondViewController : UIViewController
// 聲明代理屬性(這里要用weakU啥!甘畅!最開始使用代理埂蕊,都會踩的坑往弓。這里先不做過多解釋。)
@property (nonatomic, weak) id<CCSecondViewControllerDelegate> delegate;
@end
然后呢蓄氧,我們在第二個控制器的按鈕點擊事件中函似,讓代理響應傳值的方法。
- (void)handleButtonEvent:(UIButton *)sender {
// 判斷代理是否存在匀们,并且已經響應了傳值方法
if (self.delegate && [self.delegate respondsToSelector:@selector(sendButtonTitleToFirst:)]) {
// 傳值
[self.delegate sendButtonTitleToFirst:sender.currentTitle];
}
[self dismissViewControllerAnimated:YES completion:nil];
}
需要在第二個控制器中做的事已經做完了缴淋。去到第一個控制器准给,在第二個控制器初始化完成的地方泄朴,將第二個控制器的代理設置為第一個控制器,遵守代理露氮,然后去實現傳值方法祖灰。
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
CCSecondViewController *vc = [[CCSecondViewController alloc] init];
// 設置代理屬性
vc.delegate = self;
[self presentViewController:vc animated:YES completion:nil];
}
// 遵守代理
@interface CCFirstViewController ()<CCSecondViewControllerDelegate>
// 實現傳值的方法
- (void)sendButtonTitleToFirst:(NSString *)string {
self.label.text = string;
}
然后呢,好像就沒有然后了畔规。局扶。。
整理一下現在兩個控制器中的代碼
#import "CCFirstViewController.h"
#import "CCSecondViewController.h"
@interface CCFirstViewController ()<CCSecondViewControllerDelegate>
@property (nonatomic, strong) UILabel *label;
@end
@implementation CCFirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 30)];
label.center = self.view.center;
[self.view addSubview:label];
self.label = label;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
CCSecondViewController *vc = [[CCSecondViewController alloc] init];
vc.delegate = self;
[self presentViewController:vc animated:YES completion:nil];
}
- (void)sendButtonTitleToFirst:(NSString *)string {
self.label.text = string;
}
@end
第二個控制器的.h文件
@protocol CCSecondViewControllerDelegate <NSObject>
- (void)sendButtonTitleToFirst:(NSString *)string;
@end
@interface CCSecondViewController : UIViewController
@property (nonatomic, weak) id<CCSecondViewControllerDelegate> delegate;
@end
.m文件
@interface CCSecondViewController ()
@end
@implementation CCSecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.frame = CGRectMake(0, 0, 100, 30);
button.center = self.view.center;
[button setTitle:@"浪漫戀星空" forState:UIControlStateNormal];
[button addTarget:self action:@selector(handleButtonEvent:) forControlEvents:UIControlEventTouchDragInside];
[self.view addSubview:button];
}
- (void)handleButtonEvent:(UIButton *)sender {
if (self.delegate && [self.delegate respondsToSelector:@selector(sendButtonTitleToFirst:)]) {
[self.delegate sendButtonTitleToFirst:sender.currentTitle];
}
[self dismissViewControllerAnimated:YES completion:nil];
}
@end
代理傳值的基本使用就是這樣了叁扫∪瑁總結一下基本的步驟。
- 1.擬定一個代理協(xié)議莫绣,聲明協(xié)議方法畴蒲。
- 2.聲明代理屬性。
- 3.使用代理对室。
- 4.設置代理屬性模燥。
- 5.遵守代理,實現代理方法掩宜。
3.Block傳值
反向傳值除了上面說到的代理傳值蔫骂,還有一種常見的傳值方式,就是Block傳值牺汤。上面的反向傳值需求再用Block的方式實現一遍辽旋。
首先,在第二個控制器中聲明一個Block檐迟,通常情況下补胚,為了代碼的可讀性,我們會為Block取一個別名锅减。
typedef void(^SendButtonTitleToFirsrBlock)(NSString *string);
上面這一行代碼呢糖儡,就是給我們的Block取了一個我們想要的名字。結構大致是這樣的 怔匣。
typedef 返回值類型(^我們想取的Block的別名)(參數);
在第二個控制器中聲明一個Block屬性
// 用我們自定義的Bolck聲明一個block屬性
@property (nonatomic, copy) SendButtonTitleToFirsrBlock block;
在按鈕的點擊事件中使用Block;
- (void)handleButtonEvent:(UIButton *)sender {
if (self.block) {
self.block(sender.currentTitle);
}
[self dismissViewControllerAnimated:YES completion:nil];
}
接下來只需要在第一個控制器中初始化第二個控制器完成的地方握联,使用Block桦沉。
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
CCSecondViewController *vc = [[CCSecondViewController alloc] init];
vc.block = ^(NSString *string) {
self.label.text = string;
};
[self presentViewController:vc animated:YES completion:nil];
}
做完這些,把工程common + R 一下金闽,我們就可以看到和代理實現了一模一樣的需求纯露。看上去也更簡單代芜。
綜上埠褪,這些就是在日常開發(fā)中常用的傳值方式。當然挤庇,代理和Block能做的事多了钞速,這里只是介紹它們傳值的簡單使用。如果你在閱讀過程中發(fā)現有不足和錯誤嫡秕,請留言指出渴语。謝謝大家。如果你覺得這篇文章能給你帶來一點點收獲昆咽,不勝榮幸驾凶!