1. 程式人生 > >UI頁面跳轉和傳值

UI頁面跳轉和傳值

一、頁面跳轉:

利用navigation實現跳轉和利用模態跳轉的區別:
navigation實現跳轉,始終在同一視窗,由導航欄來管理不同的viewController的載入和退出,因此導航欄始終在。
模態實現跳轉,是新建一個視窗,如果需要新的視窗也具有導航欄,那麼要重新設定導航欄。

二、傳值

在從view1跳轉到view2的前提下,根據傳值的方向可劃分為兩種情況:

情況一:從view1傳值到view2

這樣種情況下,view2是由view1建立的,view1獲得了對view2的引用,自熱也可以訪問view2的屬性。因此,view1要傳值傳給view2就直接修改view2的屬性值就可以了。

情況二:從view2傳值回view1

由於是從view1跳轉到view2,view2不能得到view1的引用,因此不可以通過直接修改view1的屬性來把自己的值傳給view1。這時候就需要用到代理模式來實現傳值了。也就是說,既然view2不能親自修改view1的變數,那view2就叫view1自己修改。實現這種思想的辦法有3種,以下一一介紹。

(1)利用代理模式傳值

代理模式的思路是:作為委託方的類負責制定協議,並且委託方的類需要有一個表示代理人的屬性delegate。任何遵守了協議的類都可以作為該協議的代理方。

代理模式的實施:首先要為作為代理方的物件指定一個物件作為其代理人,也就是給這個物件的delegate屬性賦值,接著委託人就可以向代理物件發出指令,讓代理人呼叫它實現的協議相關方法來實施工作。
特點,方法實現的位置在代理方的類,因此在方法中可以獲取和修改代理方的例項變數。因此,委託方可以利用這一點,差遣代理方修改代理方的屬性。

回到傳值的話題上,如果需要將view2的值傳回到view1,也就是view2需要改變view1某個例項變數的值,此時,view2應該作為委託方,view1作為代理方。這樣在view2回到view1之前,就可以叫view1呼叫其實現的方法來儲存好這個要傳的值。當然實現這一步的前提是已經將view1確定為view2的delegate。那麼在view2不能獲取對view1的引用的情況下又怎麼將view1確定為view2的delegate呢?其實很簡單,雖然view2獲取不了view1的引用,但是view1可以獲取view2的引用,那麼只要在view1跳轉到view2之前,讓view1把自己設為view2的代理就可以了。(在下面第(4)點給出這個方法的例子)。

(2)利用block傳值

利用block傳值的關鍵在於,將block的定義和block的實現分開,這與代理模式有異曲同工之妙。代理模式就是將方法的宣告(委託方指定的協議)和方法的實現(代理完成具體的方法實現)分開。

與方法的實現類似,在block的具體實現中也可以獲取到其所在環境的例項變數和物件,因此,利用這一點,引用了這個block的類就可以修改block所在環境的屬性值。

在傳值的時候,如果要將view2的值傳回到view1,也就是view2需要改變view1某個例項變數的值,因此block應該在view1中實現,而view2要獲得對這個block的引用(通常以屬性的方式),以便可以呼叫它。那麼只要保證在從view1跳轉到view2之前,把view1中實現的block的引用先傳給了view2,那麼在view2跳轉回view1的時候,就可以呼叫這個block來把view2的值傳給view1了。(在下面第(5)點種給出這個方法的例子)

(3)利用方法回撥block傳值

這個方法和利用block傳值的原理其實一樣,就是把block的定義和block的實現分開,區別就在於,block的定義不是以一個屬性的形式存在於view2中,而是作為view2的一個方法的引數,而block的實現是在view1中呼叫view2的這個方法時給出。這樣的好處有兩個:一是傳值的命令是在view1中發出的,只要建立了view2物件,就可以通過呼叫view2的方法進行傳值,與是否跳轉到view2無關。二是在方法中可以實現雙向傳值(具體看例子)。(在下面第(6)點種給出這個方法的例子)

(4)代理傳值的例子:

從view1跳轉到view2,再從view2回到view1時,把view2的背景顏色傳給view1,並且改變view1的背景顏色。

1.首先是方法的定義(協議的定義):

view2中定義協議,協議中有一個方法,用來改變代理view的背景色

@protocol getColor<NSObject>
-(void)setBgColorToColorFromDelegte:(UIColor *)color;
@end

view2還需要有一個遵守該協議的代理

@interface SenconViewController : UIViewController<UITextFieldDelegate>
@property (nonatomic,retain)id <getColor> delegate;
@end

2.方法的實現(代理遵守協議)

讓view1遵守協議

@interface FirstViewController : UIViewController<getColor>
@end

並實現協議方法

-(void)setBgColorToColorFromDelegte:(UIColor *)color{
    self.view.backgroundColor=color;
}

3.方法的呼叫(設定代理,差遣代理,實現傳值)

在從view1跳轉到view2的之前將view2的代理設定為view1

view2.delegate=self;
[self.navigationController pushViewController:view2 animated:YES];

在view2中呼叫代理(也就是view1)的方法,更改view1的背景色

[self.delegate setBgColorToColorFromDelegte:self.view.backgroundColor];

(5)block傳值的例子

同樣是在view2的背景色傳給view1,並設定view1的背景色為相同的顏色。

1.方法的定義(block的定義)

view2中定義block屬性:

@property (nonatomic,copy)  void(^functionBlock)(UIColor *color);

2.方法的實現(block的實現)

view1跳轉到view2之前,給出block的實現:

 view2.functionBlock=^(UIColor *color){
        self.view.backgroundColor=color;
    };
[self.navigationController pushViewController:view2 animated:YES];

3.方法的呼叫(呼叫block實現傳值)

在view2中呼叫block,改變view1的背景色:

-(void)viewWillDisappear:(BOOL)animated{
    _functionBlock(self.view.backgroundColor);
}

(6)方法回撥block傳值的例子

根據view1傳過來的Bool值來決定是否將view2的背景色傳給view1。

1.block的定義及呼叫(block所在方法的定義及實現)

在view2中定義一個帶block引數的方法:

-(void)setChangeBgColorOrNot:(BOOL)change UsingBlock:(ChangeColorBlock )block;

實現該方法

-(void)setChangeBgColorOrNot:(BOOL)change UsingBlock:(ChangeColorBlock )block{
    if (changeOrNot==YES) {
        block(self.view.backgroundColor);
    }
}

2.block的實現(block所在方法的呼叫)

在view1中,呼叫view2的方法,並提供block的實現:

[view2 setChangeBgColorOrNot:YES UsingBlock:^(UIColor * color){
    self.view.backgroundColor=color;
}];

這就實現了雙向傳值。