淺談iOS 開(kāi)發(fā)中的界面通信

在任何的軟件開(kāi)發(fā)中都離不開(kāi)界面與界面之間的通信,界面通信的最直接的方法就是界面?zhèn)髦?

在開(kāi)發(fā)過(guò)程中我們?cè)陧?yè)面?zhèn)髦禃r(shí)我們通常使用的方法有:屬性傳值法,block傳值法,代理傳值法,以及單例傳值法,通知傳值法

屬性傳值

屬性傳值多用于在將前一個(gè)頁(yè)面的值傳到后一個(gè)頁(yè)面去,也就是我們通常說(shuō)的從前往后傳值

當(dāng)?shù)谝粋€(gè)頁(yè)面push到第二個(gè)頁(yè)面的時(shí)候,我們?cè)诘诙€(gè)頁(yè)面聲明一個(gè)屬性用于接受從第一個(gè)頁(yè)面?zhèn)鬟f過(guò)去的值,然后在push這個(gè)事件被觸發(fā)的時(shí)候進(jìn)行賦值,也就是說(shuō),先初始化創(chuàng)建第二個(gè)控制器(頁(yè)面),然后通過(guò)創(chuàng)建的控制器來(lái)訪問(wèn)它所對(duì)應(yīng)的屬性,將即將傳遞的值賦給它,這樣就完成了屬性傳值.于是當(dāng)頁(yè)面(控制器)被push到第二個(gè)頁(yè)面之后我們?cè)L問(wèn)它的屬性的時(shí)候,也就順便獲取到了傳遞過(guò)來(lái)的值.

例如:現(xiàn)在有兩個(gè)控制器FirstViewController和SecondViewController.我們?cè)贔irstViewController中創(chuàng)建一個(gè)UITextFiled,在SecondViewController中創(chuàng)建一個(gè)UILabel,然后在textField中輸入文字,我們使用導(dǎo)航控制器來(lái)控制頁(yè)面之間的跳轉(zhuǎn),當(dāng)我們跳轉(zhuǎn)到第二個(gè)頁(yè)面的時(shí)候,將在textField中輸入的文字傳遞給label,作為label上的文字.

代碼如下:

FirstViewController中:

self.navigationItem.title = @"First";
// 設(shè)置控制器的背景顏色
self.view.backgroundColor = [UIColor yellowColor];
// 設(shè)置控制器的右按鈕,并創(chuàng)建事件點(diǎn)擊調(diào)到下一頁(yè)面
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"第二頁(yè)" style:UIBarButtonItemStyleDone target:self action:@selector(next:)];
// 創(chuàng)建輸入框
self.firstTF = [[UITextField alloc] initWithFrame:CGRectMake(50, 100, 314, 40)];
self.firstTF.placeholder = @"請(qǐng)輸入文字!";
_firstTF.borderStyle = UITextBorderStyleLine;
[self.view addSubview:_firstTF];

SecondViewController中:

self.navigationItem.title = @"Second";
self.view.backgroundColor = [UIColor cyanColor];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStyleDone target:self action:@selector(back:)];
self.secondLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 100, 314, 40)];
self.secondLabel.backgroundColor = [UIColor orangeColor];
// 由上一個(gè)頁(yè)面通過(guò)屬性傳值傳過(guò)來(lái)
self.secondLabel.text = _tfString;
[self.view addSubview:_secondLabel];

我們?cè)赟econdViewController的.h文件中設(shè)置一個(gè)字符串屬性用來(lái)接收從FirstViewController中傳遞過(guò)來(lái)的值.

@property(nonatomic,strong)NSString *tfString;

那么我們?cè)谑裁磿r(shí)候傳遞這個(gè)值呢?

合適的地方應(yīng)該是在第一個(gè)頁(yè)面跳轉(zhuǎn)到第二個(gè)頁(yè)面的時(shí)候創(chuàng)建,也就是在push方法執(zhí)行之前進(jìn)行傳值.我們?cè)贔irsrViewController的右按鈕點(diǎn)擊事件也就是next方法中進(jìn)行傳值.

-(void)next:(UINavigationController *)sender{
    ScondViewController *secondNC = [[ScondViewController alloc] init];
    // 將第一個(gè)界面的輸入框信息賦值給第二個(gè)頁(yè)面的Label
    secondNC.tfString = _firstTF.text;
    [self.navigationController pushViewController:secondNC animated:YES];   
}

這樣就實(shí)現(xiàn)了從前往后傳值,也就是屬性傳值

代理傳值

代理傳值多用于從后往前傳值.

我們還是使用上面的額例子,比如我們現(xiàn)在在SecondViewController中進(jìn)行的相關(guān)的操作,現(xiàn)在我們要返回到第一個(gè)頁(yè)面,但是我們現(xiàn)在有一個(gè)需求就是需要在SecondViewController中創(chuàng)建一個(gè)UITextField,在FirstViewController中創(chuàng)建一個(gè)UILabel,當(dāng)頁(yè)面pop回第一個(gè)頁(yè)面的時(shí)候?qū)econdViewController中textField中的文字傳遞到FirstViewController中的label上,這個(gè)時(shí)候,我們就可以使用代理傳值.

我們?cè)赟econdViewController的.h中創(chuàng)建一個(gè)協(xié)議,并且設(shè)置代理屬性,讓其遵循該協(xié)議.

代碼如下:

// 設(shè)置一個(gè)協(xié)議方法
@protocol SecondVCDelegate 
    // 代理傳值 
    - (void)passValue:(NSString *)value;
@end
// 聲明代理屬性進(jìn)行代理傳值
@property(nonatomic,weak)id delegate;

在SecondViewController中創(chuàng)建textField

    self.secondTF = [[UITextField alloc] initWithFrame:CGRectMake(50, 200, 314, 40)];
    self.secondTF.placeholder = @"請(qǐng)輸入";
    self.secondTF.borderStyle = UITextBorderStyleLine;
    [self.view addSubview:_secondTF];

在FirstViewController中創(chuàng)建label并讓其遵循協(xié)議

#import "FirstViewController.h"
#import "ScondViewController.h"
@interface FirstViewController ()

@property(nonatomic,strong)UILabel *firstLab;

@end

創(chuàng)建UILabel

    self.firstLab = [[UILabel alloc] initWithFrame:CGRectMake(50, 200, 314, 40)];
    self.firstLab.backgroundColor = [UIColor magentaColor];
    [self.view addSubview:_firstLab];

我們?cè)谏鲜鰧傩詡髦荡a中已經(jīng)為SecondViewController的導(dǎo)航控制器設(shè)置了右按鈕(返回按鈕),那么,我們只需要在其觸發(fā)事件(back:)中讓代理去執(zhí)行傳值即可.
代碼如下:

- (void)back:(UINavigationController *)sender{
    // 代理去執(zhí)行傳值
    [_delegate passValue:_secondTF.text];
    [self.navigationController popViewControllerAnimated:YES]; 
}

然后在FirstViewController的next方法中為SecondNC制定其代理為其自身即可.

實(shí)現(xiàn)其代理方法

- (void)passValue:(NSString *)value{
    _firstLab.text = value; 
}

這樣我們就可以在第一個(gè)頁(yè)面得到第二個(gè)頁(yè)面的值了.

block傳值

block的本質(zhì)就和其他OC中變量類似,只不過(guò),block中存儲(chǔ)的數(shù)據(jù)是函數(shù)體,但是在使用block時(shí)完全可以像調(diào)用其他函數(shù)似的,傳入?yún)?shù),然后得到返回值.關(guān)于詳細(xì)的block,在這里就不贅述了.

在iOS開(kāi)發(fā)中我們用到block進(jìn)行傳值的情況多數(shù)情況下也是在從后往前傳值.所以我們依然使用上述例子.

使用block傳值,首先我們需要在SecondViewController中定義并聲明block屬性.

// 定義有參無(wú)返回值的匿名函數(shù)(傳遞字符串)
typedef void(^MyBlock)(NSString *);
@interface SecondViewController : UIViewController
@property(nonatomic,copy)MyBlock block;
@end

同上,我們將SecondViewController中textField中輸入的文字傳遞到FirstViewController中的label上顯示.

我們?cè)赟econdViewController的back方法中調(diào)用block,并且將在這個(gè)控制器的textField中的文字作為block的參數(shù)傳遞給block.

- (void)back:(UINavigationController *)sender{
    // 代理去執(zhí)行傳值
    self.block(_secondTF.text);
    [self.navigationController popViewControllerAnimated:YES]; 
}

然后我們?cè)贔irstViewController的next方法中,也就是alloc出SecondViewController的時(shí)候調(diào)用SecondViewController的block,實(shí)現(xiàn)傳值

- (void)back:(UINavigationController *)sender{
    __weak typeof(self)temp = self;
    secVC.block = ^(NSString *string){
        // 通過(guò)回調(diào)將傳進(jìn)來(lái)的字符串賦值給label
        temp.firstLab.text = string;
    };
    [self.navigationController popViewControllerAnimated:YES]; 
}

在上述代碼中,因?yàn)閎lock里面不能直接使用屬性,實(shí)例變量和方法(因?yàn)闀?huì)造成循環(huán)引用),所以我們重新用__weak修飾self并重新命名為temp.這樣我們就實(shí)現(xiàn)了傳值.

單例傳值

由于單例在內(nèi)存中只創(chuàng)建一次的并且可以全局訪問(wèn)的屬性,我們可以在必要的時(shí)候?qū)?shù)據(jù)存放在單例的屬性中,并且在必要的時(shí)候從單例中通過(guò)訪問(wèn)其屬性進(jìn)行調(diào)用,這樣就實(shí)現(xiàn)值的傳遞

首先我們先創(chuàng)建一個(gè)單例類DataHandle,在其.h文件中我們使用類方法聲明單例創(chuàng)建的方法,并且聲明一個(gè)字符串屬性用來(lái)保存值,(因?yàn)槲覀円廊皇褂蒙鲜龅睦?所以聲明字符串,來(lái)保存textField中輸入的文字,在實(shí)際的開(kāi)發(fā)過(guò)程中,讀者可以自己根據(jù)實(shí)際情況而定).

@interface DataHandle : NSObject
// 創(chuàng)建單例
+ (instancetype)sharedDataHandle;
@property(nonatomic,strong)NSString *Str;
@end

在.m文件中實(shí)現(xiàn)其初始化方法

@implementation DataHandle
// 聲明靜態(tài)區(qū)對(duì)象的原因,希望程序運(yùn)行期間,在內(nèi)存中一直存在,這樣對(duì)外界來(lái)說(shuō),可以隨時(shí)讀取數(shù)據(jù)
static DataHandle *dataHandle = nil;
// 創(chuàng)建單例(全局區(qū))
+ (instancetype)sharedDataHandle{
    if (nil == dataHandle) {
        // 我們創(chuàng)建單例使用加號(hào)方法的原因是因?yàn)?在創(chuàng)建之前,無(wú)法存在一個(gè)實(shí)例對(duì)象去調(diào)用動(dòng)態(tài)方法來(lái)創(chuàng)建它本身
        dataHandle = [[DataHandle alloc] init];
    }
    return dataHandle; 
}
@end

無(wú)論是從FirstViewController中將textField的值傳到SecondViewController的label上還是反過(guò)來(lái)傳值.我們只需要在需要的時(shí)候通過(guò)其類方法(+ (instancetype)sharedDataHandle)來(lái)創(chuàng)建出單例對(duì)象來(lái),然后將textField的text屬性以賦值的方式賦給單例的Srt屬性即可

代碼如下:

-(void)next:(UINavigationController *)sender{
    DataHandle *dataHandle = [DataHandle sharedDataHandle];
    ScondViewController *secondNC = [[ScondViewController alloc] init];
    // 將第一個(gè)界面的輸入框信息賦值給第二個(gè)頁(yè)面的Label
    dataHandle.Str = _firstTF.text;
    [self.navigationController pushViewController:secondNC animated:YES];   
}

假使在SecondViewController中我們?yōu)閘abel的text賦值,而其值就是FirstViewController中在textField中輸入的值,那么我們可以這樣寫(xiě):

DataHandle *dataHandle = [DataHandle sharedDataHandle];
self.secondLabel.text = dataHandle.str;

如上所述就實(shí)現(xiàn)了值的傳遞.
其實(shí)單例不知是在兩個(gè)頁(yè)面之間進(jìn)行傳遞,由于單例的一次創(chuàng)建全局訪問(wèn)的特點(diǎn),我們可以將值傳遞到ThreeViewController,FourViewController等等的控制器,相反的也可以反向傳遞,在此就不在重復(fù)了,其實(shí)原理都是相同的.

通知傳值

通知在iOS開(kāi)發(fā)中占據(jù)著非常重要的地位,通常在兩個(gè)頁(yè)面關(guān)聯(lián)不大,但是需要傳遞信息的時(shí)候傳遞,這樣就可以通過(guò)通知來(lái)實(shí)現(xiàn).

我們新建一個(gè)控制器來(lái)一鍵切換所有控制器的背景顏色.我們?yōu)槠淙∶麨?SettingViewController

創(chuàng)建一個(gè)UIButton來(lái)控制背景顏色的切換.并且為其設(shè)置觸發(fā)事件
在其出發(fā)事件中我們發(fā)送消息,并且設(shè)置通知的name為"change"用來(lái)標(biāo)記通知,設(shè)置userInfo,userInfo是一個(gè)字典,我們需要將所有控制器的顏色設(shè)置為灰色,于是,我們?cè)趧?chuàng)建字典的時(shí)候其Value值為[UIColor lioghtGrayConlor].

- (void)changeColor:(UIButton *)sender {   
    // 發(fā)送消息
    [[NSNotificationCenter defaultCenter] postNotificationName:@"change" object:nil userInfo:@{@"color":[UIColor lightGrayColor]}];
}

這樣當(dāng)我們點(diǎn)擊該button的時(shí)候,就發(fā)送了一條消息.在其他控制器里,我們?cè)O(shè)置觀察者,注冊(cè)消息.

// 注冊(cè)消息
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(changeTheme:) name:@"change" object:nil];

當(dāng)收到消息之后,就會(huì)執(zhí)行changeTheme:方法,我們就可在該方法中獲取發(fā)送的消息中所傳遞過(guò)來(lái)的數(shù)據(jù)(顏色信息),進(jìn)行控制器背景顏色的改變.

- (void)changeTheme:(NSNotification *)sender{ 
    self.view.backgroundColor = sender.userInfo[@"color"];  
}

在所有控制器里都添加觀察者注冊(cè)消息,并且實(shí)現(xiàn)changeTheme方法就實(shí)現(xiàn)了背景顏色的切換,而sender.userInfo[@"color"]就是從其他控制器中傳遞過(guò)來(lái)的值.我們可以改變userInfo這個(gè)字典的信息,從而實(shí)現(xiàn)其他類型的值的傳遞.

總結(jié)

以上介紹了五種界面通信的方法,由于筆者自身水平有限,其中難免會(huì)有疏漏,還請(qǐng)讀者指正,如果有不明白的問(wèn)題,歡迎在評(píng)論區(qū)留言討論指教,我將不勝感激,另,轉(zhuǎn)載請(qǐng)注明出處......

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末敲茄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子搁宾,更是在濱河造成了極大的恐慌折汞,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盖腿,死亡現(xiàn)場(chǎng)離奇詭異爽待,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)翩腐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)鸟款,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人茂卦,你說(shuō)我怎么就攤上這事何什。” “怎么了等龙?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵处渣,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我蛛砰,道長(zhǎng)罐栈,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任泥畅,我火速辦了婚禮荠诬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己柑贞,他們只是感情好方椎,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著钧嘶,像睡著了一般棠众。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上有决,一...
    開(kāi)封第一講書(shū)人閱讀 52,262評(píng)論 1 308
  • 那天摄欲,我揣著相機(jī)與錄音,去河邊找鬼疮薇。 笑死,一個(gè)胖子當(dāng)著我的面吹牛我注,可吹牛的內(nèi)容都是我干的按咒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼但骨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼励七!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起奔缠,我...
    開(kāi)封第一講書(shū)人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤掠抬,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后校哎,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體两波,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年闷哆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了腰奋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡抱怔,死狀恐怖劣坊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情屈留,我是刑警寧澤局冰,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站灌危,受9級(jí)特大地震影響康二,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜乍狐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一赠摇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦藕帜、人聲如沸烫罩。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)贝攒。三九已至,卻和暖如春时甚,著一層夾襖步出監(jiān)牢的瞬間隘弊,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工荒适, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留梨熙,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓刀诬,卻偏偏與公主長(zhǎng)得像咽扇,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子陕壹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 在iOS開(kāi)發(fā)過(guò)程中,界面間數(shù)據(jù)傳輸是最為基本的需求质欲,蘋(píng)果公司為我們開(kāi)發(fā)中提供了多種傳值方式,今天我們來(lái)談一談?shì)^為常...
    呼嚕ZR閱讀 7,193評(píng)論 2 38
  • 在我們需要在另一個(gè)頁(yè)面中獲取到這個(gè)頁(yè)面?zhèn)€的數(shù)據(jù)的時(shí)候九昧,我們就需要將這個(gè)頁(yè)面通過(guò)某種形式傳遞給另一個(gè)頁(yè)面。在這里我們...
    Joker_King閱讀 5,504評(píng)論 5 16
  • 在進(jìn)行頁(yè)面跳轉(zhuǎn)時(shí)毕匀,往往都需要攜帶數(shù)據(jù)耽装,以便于對(duì)界面進(jìn)行數(shù)據(jù)的初始化,方便用戶查看一些信息期揪、狀態(tài)等掉奄,以下是本人在開(kāi)發(fā)...
    笑望書(shū)閱讀 1,418評(píng)論 0 2
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)凤薛,斷路器姓建,智...
    卡卡羅2017閱讀 134,701評(píng)論 18 139
  • 不知道為什么速兔,晚上到可坊頌喝奶茶看雜志的時(shí)候很巧的碰上了上回同事介紹的相親對(duì)象。同樣的下雨天活玲,同樣有格調(diào)的背景音樂(lè)...
    滴答滴答滴閱讀 1,135評(píng)論 0 1