iOS轉場及傳值

作為初學者, 有錯誤的地方還請大神們挑出, 本人接受批評, 多謝各位大神了

iOS轉場: (RootViewController, SecondViewController)

<#(nonnull UIViewController *)#>: 目標viewController

animated: 是否存在動畫

//Show: 選擇Show,目的地視圖會被壓入導航棧頂部. 導航條會提供一個后退按鈕,用以返回源視圖. 這是最常用的方式.
//Show detail:與Show相似, 但會替換源視圖. 將沒有導航條和后退按鈕.
[self.navigationController pushViewController:delita animated:YES];
[self.navigationController showViewController:delita sender:<#(nullable id)#>

completion: 轉場之后做什么, 是一個block函數

//Present Modally: 模態顯示內容.目的地視圖會從底向上彈出, 通常用于顯示跟頁面連貫性不強的視圖, 比如 添加餐館, 添加用戶(無論在哪個頁面,都可能會調用此功能)
self.navigationController presentViewController:<#(nonnull UIViewController *)#> animated:<#(BOOL)#> completion:<#^(void)completion#>

Present as popover:iPad中常用,模態顯示一個帶箭頭指向圓角矩形彈窗. 類似一個彈出菜單.

轉場傳值:

1. 屬性傳值

//轉場方法
- (void)btnAction:(UIButton *)btn{
    SecondViewController *sec = [[SecondViewController alloc] init];//獲取目標場景
    sec.string = self.label.text;//string為目標場景中的屬性(NSString)
    [self.navigationController pushViewController:sec animated:YES];//轉場
}

2. 代理傳值(反向轉場)

1. 設置代理

@protocol SecondViewControllerDelegate <NSObject>
@optional
- (void)changeTitle:(NSString *)title;
@end

2. 在SecondViewController.h定義代理

@property (nonatomic, assign) id<SecondViewControllerDelegate>delegate;

3. 在SecondViewController.m使用代理傳值

- (void)backAction:(UIButton *)btn{
    if (self.delegate && [self.delegate respondsToSelector:@selector(changeTitle:)]) {//判斷是必須的
        [self.delegate changeTitle:self.textField.text];
    }
    [self.navigationController popToRootViewControllerAnimated:YES];
}

4. 在RootViewController.m中遵循代理并且實現代理方法

記得讓SecondViewController指定代理人為RootViewController.m

- (void)changeTitle:(NSString *)title{
    self.navigationItem.title = title;
}

3. block 傳值

block定義

/**
     *    //定義一個參無返回值的block函數
     *    void 無返回值
     *
     *    @param ^ block名稱
     *
     *    @^() 無參數
     */
    void (^voidFunc)() = ^(){
        NSLog(@"我是一個代碼塊");
    };
    //使用block
    voidFunc();
/**
     *    定義一個實現輸出兩個整數之和的block函數
     *    void 無返回值
     *    @param (int , int )類型說明
     *    @param a 參數
     *    @param b 參數
     */
    void (^addBlock)(int , int ) = ^(int a, int b){
        NSLog(@"a + b = %d", a + b);
    };
    addBlock(4, 6);
/**
     *    block命別稱
     *
     *    @param void (^)(int , int) 函數類型
     *    @param Block 別名
     */
    typedef void (^Block)(int ,int );
    //給一個參數為兩個整數, 返回值為整形的block類型命別稱
    typedef int (^addTwo)(int ,int );
    //block使用
    addTwo subBlock = ^(int a, int b){
        return a-b;
    };
    //block中沒有使用局部變量, block存儲在全局區,
    //block中如果有使用全局變量, 則存儲在棧區
    subBlock(10, 5);

block傳值步驟

1. 在SecondViewController.h給block命別稱(一般不省略)
typedef void(^titleBlock)(NSString *title);
2. 在SecondViewController.h中定義一個block屬性
@property (nonatomic, copy) titleBlock myBlock;
//注意: block屬性必須用copy
//block使用全局變量, 存在棧區, 使用copy是把block復制一份到堆區
3. 在跳轉頁面方法中給block屬性賦值(RootViewController的btnAction:)
    //在block中使用局部變量
    //__block(MRC)/__weak(ARC)
    __weak RootViewController *temp = self;//復制指針(引用計數不變)
    //不使用temp而用self, 在下個界面會持有self, 引用計數會+1
    //使用self容易造成循環引用(MRC下)
    sec.myBlock = ^(NSString *title){
        temp.navigationItem.title = title;
    };
4. 調用block屬性傳入參數
- (void)backAction:(UIButton *)btn{
    self.myBlock(self.textField.text);
    [self.navigationController popToRootViewControllerAnimated:YES];
}

單例模式傳值

1. 新建一個單例模式, 這里新建一個類白包含單例模式(User)

//在User.h中定義一些屬性, 這些屬性作為存取值的對象
@property (nonatomic, strong) NSString *userName;
@property (nonatomic, strong) NSString *passworld;
//設計一個單例模式初始化
//獲取唯一的用戶
+ (User *)defaultUser;

2. 實例化初始化

+ (User *)defaultUser{
    //static修飾的對象只會在第一次調用函數時初始化, 之后不再初始化
    static User *user = nil;
   if(user == nil){//判斷user是否為空, 空則初始化
       user =[ [User alloc] init];
   }
   return user;
}

2. 在RootViewController.m中導入User.h, 同時在viewWillAppear(界面即將顯示)中獲取單例模式的值

- (void)viewWillAppear:(BOOL)animated{
    self.textField.text = [User defaultString].string;
}

3. 在轉場按鈕函數中將值存入User中

- (void)btnAction:(UIButton *)btn{
    SecondViewController *sec = [[SecondViewController alloc] init];
    //獲取單例
    User *u = [User defaultString];
    //賦值
    u.string = self.textField.text;
    [self.navigationController pushViewController:sec animated:YES];
}
注: 如果需要讓RootViewController一開始就顯示, 比如讓textField一開始就顯示"單例模式"
//在viewDidLoad中直接初始化User并存值
self.textField.text = @"單例模式";
[User defaultString].string = self.textField.text;

4. 在SecondViewController中使用User中的string給self.textField.text賦值

self.textField = [[UITextField alloc] initWithFrame:CGRectMake(50, 200, 200, 50)];
    self.textField.borderStyle = UITextBorderStyleRoundedRect;
    self.textField.text = [User defaultString].string;
    self.textField.delegate = self;
    self.textField.textAlignment = NSTextAlignmentCenter;
    self.textField.clearButtonMode = UITextFieldViewModeAlways;
    [self.view addSubview:self.textField];

5. 在按鈕返回函數中存儲數據

- (void)btnAction:(UIButton *)btn{
    User *u = [User defaultString];
    u.string = self.textField.text;
    [self.navigationController popViewControllerAnimated:YES];//返回上層界面
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容