分享三種常用的頁面傳值方法
阿新 • • 發佈:2019-02-12
本篇文章羅列了三種頁面之間的傳值方式(實際當然不止三種啦^_^),也是博主認為比較常用的方法,沒有什麼花俏,但是幾乎每個app裡面都要用到所謂的傳值。所以,今天將這三種方法寫下來,一來記錄自己的開發生涯,二來可以和廣大初學者交流共勉。
工程中建立了一個NavgationController,它的rootViewController是ViewController,另外再建立一個SubViewcontroller作為要push的子頁面,整個工程搭建就是這樣,下面上程式碼。
第一種:Block反向傳值
Viewcontroller.m
#import "ViewController.h"
#import "SubViewController.h"
@interface ViewController ()
{
UILabel *label;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.title = @"first";
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setFrame:CGRectMake(30, 200, 80, 30)];
[btn setTitle:@"button" forState:UIControlStateNormal];
[btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[btn setBackgroundColor:[UIColor grayColor]];
[self.view addSubview:btn];
[btn addTarget:self action:@selector(buttonTouch) forControlEvents:UIControlEventTouchUpInside];
label = [[UILabel alloc] initWithFrame:CGRectMake(90, 300, 200, 50)];
label.layer.borderColor = [UIColor grayColor].CGColor;
label.layer.borderWidth = 1.5;
label.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:label];
}
Viewcontroller中建立一個btn,做點選時push子頁面用,下面建立一個label,等待接收我們傳入的text值。
SubViewcontroller.h
#import <UIKit/UIKit.h>
typedef void(^Test)(NSString *str); //block
@interface SubViewController : UIViewController
@property (nonatomic, strong) NSString *navTitle;
@property (nonatomic, strong) Test test;
@end
在子頁面SubViewcontroller.h中宣告我們需要的block,返回值為void,帶有一個NSString型別的引數str,navTitle是從Viewcontroller傳入的,做為子頁面導航欄的標題(正向傳值),test即為我們建立的回撥物件。接下來是主頁面btn方法的實現
- (void)buttonTouch
{
SubViewController *subVC = [[SubViewController alloc] init]; //1
subVC.navTitle = @"second";//2
subVC.test = ^(NSString *text){ //3
label.text = text;
}; //4
[self.navigationController pushViewController:subVC animated:YES]; //5
}
點選首頁面btn,程式碼執行順序如上所標,label.text = text;是回撥中的方法,只有觸發回撥才會執行,並且傳入的引數會儲存在text中,隨後賦值給label.text。如果回撥沒有觸發則label.text = text;將永遠不執行。
@implementation SubViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.navigationItem.title = self.navTitle;
self.view.backgroundColor = [UIColor whiteColor];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setFrame:CGRectMake(30, 200, 80, 30)];
[btn setTitle:@"subButton" forState:UIControlStateNormal];
[btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[btn setBackgroundColor:[UIColor grayColor]];
[self.view addSubview:btn];
[btn addTarget:self action:@selector(subButtonTouch) forControlEvents:UIControlEventTouchUpInside];
}
- (void)subButtonTouch
{
self.test(@"value1"); //觸發回撥
}
第二種:我也不知道叫什麼名字好。。
原理很簡單,在首頁面寫下一個setLabelText:方法,當頁面跳轉時,將首頁的self和setLabelText:傳入子頁面並儲存,隨後在子頁面點選btn時,呼叫接收到的”self“(不是子頁面self)呼叫接收到的方法即可,這樣就相當於在子頁面的時候操作了主頁面的物件。
@property (nonatomic, strong) id myTarget;
@property (nonatomic, assign) SEL mySelector;
在子頁面.h檔案建立接收首頁物件和方法的物件(表達很繞口)
- (void)buttonTouch
{
SubViewController *subVC = [[SubViewController alloc] init];
subVC.navTitle = @"second";
subVC.myTarget = self;
subVC.mySelector = @selector(setLabelText:);
[self.navigationController pushViewController:subVC animated:YES];
}
- (void)setLabelText:(NSString *)text
{
label.text = text;
}
首頁的改動,新增setLabelText:方法作為引數傳遞到子頁面。- (void)subButtonTouch
{
[self.myTarget performSelector:self.mySelector withObject:@"value2"];
}
子頁面btn點選方法只需一句,有警告但不影響程式執行。
第三種:通知
通知就更簡單了,舉個例子幫助大家理解。有一座山,山頂和半山腰各站著一個人,山頂的人大喊一聲,這時整個山周圍都聽得到,當然半山腰的那個人頁聽到並回應了山頂的人,這樣他們兩人之間就做了一次訊息的傳送。實際中,這座山就是我們的app,山頂的人就是通知的發出者,通知遍佈整個app,可以存在於app任何地方;半山腰的人就是通知的接受者之一,接收到通知後就執行相應的程式碼。
注意:1.通知一旦傳送,整個app都可以檢測到
2.可以同時傳送多個通知,但每個通知命名不能相同
3.同一個通知可以被多個觀察者監聽,一個觀察者只能監聽一個通知
- (void)subButtonTouch
{
[[NSNotificationCenter defaultCenter] postNotificationName:@"label_text_notifiction" object:self userInfo:@{@"test":@"value3"}];
}
只需要在子頁面btn點選時傳送一個名為label_text_notifiction的通知,附帶引數為鍵值對test = value3。[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(recieveNotifiction:) name:@"label_text_notifiction" object:nil];
在首頁的viewDidLoad中建立監聽者,注意通知命名要相同
- (void)recieveNotifiction:(NSNotification *)noti
{
NSDictionary *dic = noti.userInfo;
NSString *str = [dic objectForKey:@"test"];
label.text = str;
}
將附帶引數解析出來賦值給label.text。
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
最後一定記得移除監聽。
總結:前兩種方法適用於頁面與子頁面之間傳值,第三種通知則沒有限制,但是通知是全域性變數,消耗記憶體較大,須謹慎使用。