iOS 頁面之間的傳值方式

在iOS開發中,爲了減少數據請求的次數和進行一些邏輯處理,常會在頁面跳轉的同時進行值得傳遞。常用的傳值方式有:屬性傳值、通知傳值、委託代理傳值、Block傳值、KVO傳值。

在說傳值之前,先來說一下頁面的跳轉。現有A、B兩個頁面,A頁面有個跳轉按鈕,當點擊按鈕的時候執行push或者present操作,頁面跳轉到下一級頁面B,這個跳轉叫做正向跳轉。當點擊B頁面中的返回按鈕,頁面返回到上一級頁面A,這樣的跳轉叫做逆向跳轉(反向跳轉)。與之對應的傳值就有了正向傳值和逆向傳值這兩種邏輯形式。

在正向跳轉的時候,要傳遞值到下一級頁面,這個時候的傳值叫做正向傳值。在開發中,常用的正向傳值方式是屬性傳值,因爲這個方式是最簡單方便的。當逆向跳轉的時候,要傳值到上一級頁面,這個時候可以選擇的方式就很多,可以是通知、代理、Block、KVO。但是具體選擇哪一個要看具體情況而定。

首先,來看看屬性傳值:

屬性,就是對象屬性,也就是一個類中的成員屬性,我們利用這個屬性可以在頁面跳轉的時候進行值得傳遞。這裏要注意的是,這個屬性必須要對外開放的,也就是外部對象可以訪問到這個屬性,纔可以進行屬性傳值。如何開放?很簡單,就是在.h文件中去聲明這個屬性就可以對外開放。下面,用代碼講解:

AViewController.m中代碼:

#import "AViewController.h"

#import "BViewController.h"


@interface AViewController ()

{

    UIButton *button;

    UILabel *label;

}

@end


@implementation AViewController


- (void)viewDidLoad {

    [super viewDidLoad];

    

    [self setUI];

}


#pragma 創建視圖

- (void)setUI{

    label = [[UILabel alloc]initWithFrame:CGRectMake(100, 200, 200, 30)];

    label.text = @"A頁面要傳遞的值";

    label.font = [UIFont systemFontOfSize:15];

    label.backgroundColor = [UIColor yellowColor];

    [self.view addSubview:label];

    

    button = [UIButton buttonWithType:UIButtonTypeCustom];

    button.frame = CGRectMake(100, 300, 200, 30);

    button.backgroundColor = [UIColor blueColor];

    [button setTintColor:[UIColor whiteColor]];

    [button setTitle:@"點擊跳轉" forState:UIControlStateNormal];

    [button addTarget:self action:@selector(push) forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:button];

}


#pragma 按鈕點擊事件,頁面跳轉

- (void)push{

    //2、創建B控制器對象。

    BViewController *bVC = [[BViewController alloc]init];

    //3、使用對象調用對象屬性,並給屬性賦值。

    bVC.string = label.text;

    //4、頁面跳轉

    [self.navigationController pushViewController:bVC animated:YES];

}


@end

BViewController.h中代碼:

#import <UIKit/UIKit.h>


@interface BViewController : UIViewController


//1、聲明屬性,用來接收傳遞的值

@property (nonatomic, copy) NSString *string;


@end

BViewController.m中代碼:

#import "BViewController.h"


@interface BViewController ()

{

    UILabel *label;

}

@end


@implementation BViewController


- (void)viewDidLoad {

    [super viewDidLoad];

    self.view.backgroundColor = [UIColor grayColor];

    

    label = [[UILabel alloc]initWithFrame:CGRectMake(100, 200, 200, 30)];

    //5、使用屬性給label賦值

    label.text = self.string;

    label.font = [UIFont systemFontOfSize:15];

    label.backgroundColor = [UIColor yellowColor];

    [self.view addSubview:label];

}


@end


運行結果:

             

在上面的運行結果可以看到,A頁面中label上的文字傳遞到了B頁面中去顯示。說明傳值是成功的。現在在回來看看屬性傳值的步驟:

//1、聲明屬性,用來接收傳遞的值

@property (nonatomiccopyNSString *string;

//2、創建B控制器對象。

BViewController *bVC = [[BViewController alloc]init];

//3、使用對象調用對象屬性,並給屬性賦值。

bVC.string = label.text;

//4、頁面跳轉

[self.navigationController pushViewController:bVC animated:YES];

//5、使用屬性給label賦值

label.text = self.string;


上面的5個步驟就是屬性傳值的“公式”了,只需要子啊要接受傳值的頁面中先定義出一個對外開放的屬性,然後再要傳值的頁面的頁面跳轉之前給要跳轉對象的屬性賦值就可以將值傳遞過去。


上面的屬性傳值只能用於正向傳值,而不能用於逆向傳值,因爲在頁面返回的時候是沒有要返回頁面的對象的,要是再創建一個上級頁面進行跳轉返回,那麼就會出現循環引用的問題。在做逆向傳值的時候,常採用的方式是另外的集中傳值方式了:通知傳值、委託代理傳值、Block傳值、KVO傳值。

這幾種傳值,在前面的文章中都已經有了介紹,這裏就不多說了。這裏要說的是在傳值的時候,具體去選擇哪一種傳值方式會更好。

首先是正向傳值,這個當然是屬性傳值更好,更方便。逆向傳值的時候,如何去選擇?這是一個問題。

在選擇之前,先來看看每種傳值方式的優點有哪些:

通知傳值:都知道,通知就是廣播機制,既然是廣播,那麼就可以讓很多的對象“聽到”,這樣的機制就使得通知在傳值的時候,可以給很多對象傳值,通知不去管有哪個對象接收,也不去管有多少個對象接收。只需要去發送通知就可以了,至於誰接收與發送通知的對象無關。這樣的優點就使得通知的傳值對象更廣。所以,在使用的時候,可以在不知道有哪個對象要接收,也不知有多少個對象需要這個傳值的時候使用。

委託代理傳值:委託代理其實就是制定協議,然後遵守協議,最後實現協議方法取值的形式。這樣的形式就是的有很強的針對性,要取值就必須要遵守協議並實現協議方法。所以,在開發中,常用來做定向定點的傳值。這裏的定向定點並不是說代理不能給很多對象傳值,只是一般不這麼做而已,因爲很多對象都遵守協議實現代理,這樣的代碼會很亂。不如通知簡單。

Block傳值:代碼塊Block傳值和代理傳值差不多,都是用來做定向定點的傳值。但是Block不需要去設置代理,不需要去設置協議。相比較於代理,代碼方面會減少很多。但是它也有個缺點,就是如果代碼中有大量的傳值操作,Block使用太多會使得代碼看着很亂不利於管理,而卻使用不當還容易引起內存泄漏。所以Block的使用要適當。

KVO傳值:KVO的原理是監聽,它監聽到對象的屬性發生變化後就會做出相應,在相應的同時可以實現值得傳遞,這樣的機制和通知差不多,用來“多方面的”傳值。


從上面的介紹來看,

通知和KVO常用來做不知對象的傳值,比如:

現在有一個開關,當開關開啓的時候,傳值1,加載網絡數據,當開關關閉時,傳值0,加載本地數據。這個時候我們就不知道有多少地方要接收0和1。所以適用通知或者KVO就很合適,不需要去管其他的,只負責把值傳出去。誰要接收誰就接收通知或者添加觀察者就好了。

代理和Block常用來做定點傳值,比如:

現在頁面上有個選擇地址的欄目,點擊這個欄目跳轉到下一級頁面中去選擇國家,當點擊選中的國家後,頁面返回,並將選中的國家的名稱傳遞回來。這樣的需求,使用代理或者Block就更合適,因爲只有在這裏使用到傳值,針對性很強。


在開發中,不同控制器之間的傳值是很重要的,傳值方式的選擇可以方便代碼的編寫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章