iOS學習之六種傳值方式

來源:互聯網
上載者:User

標籤:

iOS頁面傳值方式

應用於:

  1. 兩個互動的介面:1)頁面一跳轉到頁面二,頁面一的textField的值傳給頁面二的label。2)A頁面跳轉到B頁面,B頁面再跳回A頁面(註冊頁面跟登入頁面)
  2. 兩個不互動的兩個介面:資料持久層跟展示層的資料互動。

幾種傳值方式:

  1. 屬性傳值 
  2. 委託delegate方式
  3. 通知notification方式
  4. block方式
  5. 單例模式方式
  6. UserDefault或者檔案方式

 

1.屬性傳值(順傳):

  1. 需要定義一個公開的屬性
  2. 需要一個你需要傳值的對象
  3. 進行屬性賦值

實現:A、B兩個介面,通過按鈕將A介面textField的值傳給頁面B的label。

A:ViewController   B:DetailViewController

#import "ViewController.h"  @interface ViewController ()  @property (nonatomic, strong) UITextField *textField; @end  @implementation ViewController-(void)buttonAction:(UIButton *)button{DetailViewController *detailViewController = [[DetailViewController alloc]init];//用下一個視圖的屬性接受想要傳過去的值,屬性傳值detailViewController.firstValue = self.txtFiled.text;[self.navigationController pushViewController:second animated:YES];}DetailViewController介面#import "DetailViewController.h"  @interface DetailViewController ()  @property (nonatomic, weak) NSString firstValue;//接收textField傳過來的值。 @end

 

2.代理傳值(順傳倒傳都可以)

delegate只能是一對一之間的。他只能是navigation的棧裡面的相鄰控制器傳值, 不能跨控制器傳值。比如:a到b,b到c.,而不能從c傳到a.

  1. 擬定?份協議(命名一般是XXXDelegate),協議裡面的?法的參數取決於你要傳遞的內容
  2. 設定代理人屬性(再次強調,使用assign防?循環參考)
  3. 在需要調?的地?調?,這?步比較抽象,?如上面所講例?子,我們是需要在button點擊的時候
  4. 傳值並且取消介面,所以我們的delegate就在這個?面的進?調用
  5. 讓相應的對象成為代理人,?般都是在建立的時候指定一個代理?
  6. 遵守協議,並且實現相應的方法,然後在方法中進行邏輯處理

 

實現:A頁面push到B頁面,如果 B頁面的資訊想回傳(回調)到A頁面,用代理傳值,其中B定義協議和聲明代理,A確認並實現代理,A作為B的代理

A頁面:RootViewControllers  B頁面:DetailViewControllers

ViewControllers.h檔案#import <UIKit/Uikit.h>@class DetailViewController;@protocol PassingValueDelegate<NSObject>//擬定協議@optional-(void)passValues:(NSString *)values;//定義協議方法(values你想要傳遞的內容)@end@interface ViewControllers: UIViewController@property (nonatomic, weak)id< PassingValueDelegate > delegate; (valueDelegate)//設定代理屬性,通過其傳值(為防止循環參考,此處採用了weak或者assign)點擊按鈕事件函數(調用代理)-(void)trendBtnClick{     //create the view   DetailViewController * detailViewController = [[DetailViewController alloc] initWithNibName:@" DetailViewController " bundle:nil]; //傳值並且取消介面    self.delegate (自己命名的valueDelegate )= detailViewController; //設定代理 ,讓相應的對象成為代理人    [self.trendDelegate passValues:@"123456"]; //頁面跳轉  }DetailViewController.h 檔案引用ViewController的標頭檔,並添加代理協議如下#import "ViewController.h" @interface TrendViewController : UIViewController<PassTrendValueDelegate>{ } @end實現代理函數:#pragma mark 實現傳值協議方法 -(void)passValues:(NSString *)values{ NSLog(@"values=%@",values);  }

 

最重要也是最容易忽略的,就是一定要設定delegate的指向

3.通知傳值(順傳倒傳都可以)第三個頁面的值傳給第一個頁面

誰要監聽值的變化,誰就註冊通知 ,特別要注意,通知的接受者必須存在這一先決條件不用通知的時候,記得移除。

  1. 在第三個介面中, 建?一個通知中樞, 通過通知中樞, 發送通知(發送通知的過程就是傳值的過程,將要傳輸的值作為object的值傳給第一個介面
  2. 在第?個介面建?一個通知中樞, 通過通知中?,註冊一個監聽事件
  3. 在第一個界?中,設定接收到通知的事件。
  4. 在第?個界?面中的dealloc中, 將通知中樞remove掉

 

任何對象對可以發送通知到中心,同時任何對象可以監聽中心的通知。
發送通知的代碼如下:

[[NSNotificationCenter defaultCenter] postNotificationName:@”myNotificationName” object:broadcasterObject]; 

註冊接收通知的代碼如下: 

[[NSNotificationCenter defaultCenter] addObserver:listenerObject selector:@selector(receivingMethodOnListener:) name:@”myNotificationName” object:nil]; 

實現:將B介面的值傳給A介面,所以B介面發送通知到通知中樞,A介面註冊成為監聽者,監聽B值的變化,接受從通知中樞回傳的B的值。如果c頁面也想接受B的值,也同樣註冊成為監聽者就行。(所以可以實現多對多)

A介面:RootViewController B介面:SecondViewController

 

B介面建立通知中樞,將要傳的值nameTextField.text通過通知中樞發送

//SecondViewController.m-(IBAction)notificationMethod:(id)sender {[[NSNotificationCenter defaultCenter] postNotificationName:@‘ChangeNameNotification‘  object:self  userInfo:@{@‘name‘:self.nameTextField.text}];[self dismissViewControllerAnimated:YES completion:nil];}在A頁面的控制器中,註冊通知://RootViewController.m- (void)viewDidLoad.{[super viewDidLoad];[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ChangeNameNotification:) name:@‘ChangeNameNotification‘ object:nil];}調用,顯示//RootViewController.m-(void)ChangeNameNotification:(NSNotification*)notification{NSDictionary *nameDictionary = [notification userInfo];self.nameLabel.text = [nameDictionary objectForKey:@‘name‘];.}當我們不使用時,要記得刪掉通知://RootViewController.m-(void)dealloc{[[NSNotificationCenter defaultCenter] removeObserver:self];}

4. block傳值(順傳倒傳都可以)block同樣用於回調

  1. 為block取別名。並且在參數列表中將需要傳遞的參數寫形參
  2. 設定block屬性(注意使用copy)
  3. 設定一個方法持有當前block
  4. 在合適的地方進行調用類似代理
  5. 在建立該對象的地方進行block方面的調用

//block文法

   //傳回值類型 (^block參數名) (參數類型 參數名) = ^傳回值類型 (參數類型 參數名)

實現:將B介面的textField.text傳給A介面的Label

A頁面:RootViewControllers  B頁面:DetailViewControllers

DetailViewController檔案

#import <UIKit/Uikit.h>typedef void (^DetailBlock)(NSString *);//block取別名。並且在參數列表中將需要傳遞的參數寫形參@interface DetailViewController : UIViewController@property (nonatomic, copy) PassingValueBlock passingvalue;//設定block屬性(注意使用copy)@property (weak, nonatomic) UITextField *inputTF;@end- (IBAction)BtnAction:(id)sender {        //判斷block是否為空白    if (self.NextViewControllerBlock) {        self.NextViewControllerBlock(self.inputTF.text);           }    [self.navigationController popViewControllerAnimated:YES];}//點擊按鈕到A介面RootViewController.m@property (strong, nonatomic) UILabel *textLabel; -(void)handleButton: (NSString*)sender{DetailViewController *detailViewController = [[DetailViewController alloc]init];detailViewController.passingValue=^( NSString* str){self. textLabel.text= str;}[self.navigationController pushViewController:detailViewController animated:YES];}

5. 單例傳值(順傳倒傳都可以)

單例的好處就在於只是建立了一次,其餘任何時候訪問到的對象都是同一個,所以很多時候用到使用者的一些資訊都是儲存在單例中的,這樣就不需要多次傳值了,只需要再次建立單例就可以了

AppStatus.h  建立一個單例類 AppStatus

#import <Foundation/Foundation.h>

@interface AppStatus : NSObject

{

    NSString *_contextStr;

}

@property(nonatomic,retain)NSString *contextStr;

+(AppStatus *)shareInstance;

@end

AppStatus.m

#import "AppStatus.h"

@implementation AppStatus

@synthesize contextStr = _contextStr;

static AppStatus *_instance = nil;

 

+(AppStatus *)shareInstance

{

    if (_instance == nil)

    {

        _instance = [[super alloc]init];

    }

    return _instance;

}

-(id)init

{

    if (self = [super init])

    {       

    }

    return self;

}

@end

RootViewController.h

#import "RootViewController.h"

#import "DetailViewController.h"

#import "AppStatus.h"

 

@interface RootViewController ()

 

@end

 

@implementation RootViewController

 

-(void)pushAction:(id)sender

{

    tf = (UITextField *)[self.view viewWithTag:1000];

 

 //單例傳值  將要傳遞的資訊存入單例中(共用中)

  //  [[AppStatus shareInstance]setContextStr:tf.text]; 跟下面這種寫法是等價的

    [AppStatus shareInstance].contextStr = tf.text;

    //導航push到下一個頁面

    

    DetailViewController *detailViewController = [[DetailViewController alloc]init];

 

    //導航push到下一個頁面

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

 

@end

DetailViewController.h

#import <UIKit/UIKit.h>

@protocol ChangeDelegate;//通知編譯器有此代理

 

@interface DetailViewController : UIViewController

{

    UITextField *textField;

}

 

@end

#import "DetailViewController.h"

#import "AppStatus.h"

 

@interface DetailViewController ()

 

@end

 

@implementation DetailViewController

 

@synthesize naviTitle = _naviTitle;

 

-(void)loadView

{

    self.view = [[[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)]autorelease];

 

    //單例

    self.title = [AppStatus shareInstance].contextStr;

    textField = [[UITextField alloc]initWithFrame:CGRectMake(100, 100, 150, 30)];

    textField.borderStyle = UITextBorderStyleLine;

    [self.view addSubview:textField];

 

    UIBarButtonItem *doneItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDonetarget:self action:@selector(doneAction:)];

    self.navigationItem.rightBarButtonItem = doneItem;

    [doneItem release];

}

 

//這個方法是執行多遍的  相當於重新整理view

-(void)viewWillAppear:(BOOL)animated

{

    [super viewWillAppear:animated];

    tf = (UITextField *)[self.view viewWithTag:1000];

    tf.text = [AppStatus shareInstance].contextStr;

}

 

//pop回前一個頁面

-(void)doneAction:(id)sender

{

    //單例傳值

    [AppStatus shareInstance].contextStr = textField.text;

    [self.navigationController popToRootViewControllerAnimated:YES];

}

6.NSUserDefault傳值(順傳倒傳都行)

[[NSUSerDefault  standardUserDefaults]setObject:要傳的值   forKey:對這個值得標記鍵];//設定值

[[NSUserDefault  standardUserDefaults]ObjectForKey:根據你的標記鍵];//擷取值

 

iOS學習之六種傳值方式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.