1. 程式人生 > >分享三種常用的頁面傳值方法

分享三種常用的頁面傳值方法

本篇文章羅列了三種頁面之間的傳值方式(實際當然不止三種啦^_^),也是博主認為比較常用的方法,沒有什麼花俏,但是幾乎每個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");   //觸發回撥
}


子頁面同樣放置一個btn,點選時觸發回撥並傳入字串@“value”,然後返回首頁就看到label已經被賦值了。


第二種:我也不知道叫什麼名字好。。

原理很簡單,在首頁面寫下一個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];
}
最後一定記得移除監聽。


總結:前兩種方法適用於頁面與子頁面之間傳值,第三種通知則沒有限制,但是通知是全域性變數,消耗記憶體較大,須謹慎使用。