UI界面傳值

傳值需求

  • 將用戶信息 userInfo 作為傳值對象進行傳遞。

場景一 主頁傳值到詳情頁

  • 現在模擬傳遞用戶名:userName。
屬性傳值
  1. 屬性傳值一般用于從主頁傳值到詳情頁。
  2. 傳值步驟:
steps 1:在DetailViewController.h文件中將需要獲取的值聲明成屬性。
#import <UIKit/UIKit.h>

@interface DetailViewController : UIViewController

@property (nonatomic, strong)NSString *userInfo; /**< 用戶信息 */

@end

steps 2:在HomeViewController.m文件中導入頭文件“DetailViewController.h”,然后在界面跳轉邏輯處理方法中初始化DetailViewController,并通過點語法給屬性userInfo賦需要傳遞的值。
- (void)respondsToButton:(UIButton *)sender {

    // 初始化詳情視圖控制器n
    DetailViewController *detailVc = [[DetailViewController alloc] init];

    // 屬性傳值:賦值
    NSDictionary *userInfo = @{@"name":@"Charles", @"age":@(22)};
    detailVc.userInfo = userInfo;

    // 模態切換(界面跳轉)
    [self presentViewController:detailVc animated:YES completion:nil];

}

steps 3:在DetailViewController.m文件viewDidLoad方法中獲取userName的值,此時獲取到的值就是從主頁傳過來的值。
- (void)viewDidLoad {
    [super viewDidLoad];

    NSLog(@"%@", userInfo);
}
init傳值
  1. init方法傳值與屬性傳值類似,一般用于從主頁傳值到詳情頁。
steps 1:在DetailViewController.h文件中聲明init方法。
- (instancetype)initWithUserInfo:(NSDictionary *)userInfo; /**< init傳值方法聲明 */
steps 2:在HomeViewController.m文件中導入頭文件“DetailViewController.h”,然后在界面跳轉邏輯處理方法中通過initWithUserInfo:方法初始化DetailViewController并賦值。
- (void)respondsToButton:(UIButton *)sender {

    NSDictionary *userInfo = @{@"name":@"Charles", @"age":@(22)};

    // 初始化詳情視圖控制器
    DetailViewController *detailVc = [[DetailViewController alloc] initWithUserInfo:userInfo];

    // 模態切換(界面跳轉)
    [self presentViewController:detailVc animated:YES completion:nil];

}
steps 3:在DetailViewController.m文件中重寫init方法,即實現initWithUserInfo:方法,在這個方法中獲取userName的值,此時獲取到的值就是從主頁傳過來的值。
- (instancetype)initWithUserInfo:(NSDictionary *)userInfo {
    if (self = [super init]) {
        NSLog(@"%@", userInfo);
    }
    return self;
}

場景二 詳情頁傳值到主頁

Block塊傳值
  • block在傳值中主要用于回調,現模擬從詳情視圖控制器傳值到主頁視圖控制器。
steps 1:在 DetailViewController.h文件中聲明block類型、屬性以及block回調方法。
#import <UIKit/UIKit.h>

// 1 聲明block類型

typedef void(^CallBackBlock)(NSString *context);

@interface DetailViewController : UIViewController

// 2 聲明block屬性

@property (nonatomic, copy) CallBackBlock callBackBlock;

/ 3 聲明block傳值方法
- (void)getsUserInfoWithBlocks:(CallBackBlock)callBackBlock;


@end
steps 2:在 DetailViewController.m文件中,實現如下操作:
// 4 賦值屬性block
- (void)getsUserInfoWithBlocks:(CallBackBlock)callBackBlock {
    self.callBackBlock = callBackBlock;
}

// 處理按鈕點擊
- (void)respondsToButtonClick:(UIButton *)sender {
    // 5 傳值
    if (self.callBack) {

        NSDictionary *userInfo = @{@"name":@"Charles", @"age":@(22)};
        self.callBackBlock(userInfo);

        [self dismissViewControllerAnimated:YES completion:nil];
    }
}
steps 3:在 ViewController.m文件實現如下操作:
- (void)respondsToButtonClick:(UIButton *)sender {
    DetailViewController *detailVc = [[DetailViewController alloc] init];

    // 6 調用block,取值
    [detailVc getsUserInfoWithBlocks:^(NSDictionary *userInfo) {
    NSLog(@"%@", userInfo);
}];

    // 模態切換(界面跳轉)
    [self presentViewController:detailVc animated:YES completion:nil];
}
  • Tips:
    1、為block取別名,可在參數列表中將需要傳遞的參數寫成形參;
    2、設置block屬性注意使用copy關鍵字;
    3、設置一個方法持有當前block;
    4、在合適的地方進行調用類似于代理;
    5、在創建該對象的地方進行block方面的調用;
協議傳值
  1. 協議傳值又稱代理傳值,可直接將需要傳遞的值從委托方傳送至代理人,協議傳值可用于從下一個視圖控制器傳值到上一個視圖控制器(詳情頁傳值到主頁),現假定主頁是詳情頁的代理。
  • 傳值步驟
steps 1:在DetailViewController.h文件中聲明協議,并且設置代理屬性。
#import <UIKit/UIKit.h>


// @class 意在告訴編譯器,“DetailViewController”為一個類。

@class DetailViewController;

// @protocol 聲明協議
// 協議命名規范:類名 + delegate

@protocol DetailViewControllerDelegate <NSObject>

// @optional:聲明可選協議方法
// 協議方法的聲明模仿蘋果官方聲明方式,將類實例以及傳遞信息一并暴露在參數中

@optional

- (void)detailViewController:(DetailViewController *)detailViewController goBackWithUserInfo:(NSDictionary *)userInfo;

@end

@interface DetailViewController : UIViewController

// 聲明代理屬性,注意關鍵字使用 weak || assign,可避免保留環
@property (nonatomic, weak) id <DetailViewControllerDelegate> delegate;
@end
steps 2:在DetailViewController.m文件處理返回按鈕方法中調用協議方法傳值。
- (void)respondsToButton:(UIButton *)sender {

    // 首先判斷代理人是否存在并且是否遵守協議并且實現了協議方法

    if (_delegate && [_delegate respondsToSelector:@selector(detailViewController:goBackWithUserInfo:)]) {

        // 如果滿足判斷條件,則讓代理執行協議方法,此處讓代理人執行協議方法,在代理人那個控制器中的協議方法會被執行;

        // 通常經協議傳值在此處調用方法時,直接給參數賦值即可,在代理人控制器實現的協議方法中,可直接獲取此處設置的值;

        NSDictionary *userInfo = @{@"name":@"Charles", @"age":@(22)};

        [_delegate detailViewController:self goBackWithUserInfo:userInfo];

    }
}
steps 3:在HomeViewController.m文件處理界面跳轉按鈕方法中初始化詳情視圖控制器,設置詳情視圖控制器協議代理為self(主頁),并且遵守<DetailViewControllerDelegate>協議。
- (void)respondsToButton:(UIButton *)sender {
    // 初始化詳情視圖控制器
    DetailViewController *detailVc = [[DetailViewController alloc] init];

    // 設置代理,并且遵守<DetailViewControllerDelegate>
    detailVc.delegate = self;

    // 模態切換(界面跳轉)
    [self presentViewController:detailVc animated:YES completion:nil];
}
steps 4:在HomeViewController.m中實現<DetailViewControllerDelegate>協議方法,獲取值。
#pragma mark *** DetailViewControllerDelegate ***
// 實現協議方法,獲取值
- (void)detailViewController:(DetailViewController *)detailViewController goBackWithUserInfo:(NSDictionary *)userInfo {
    NSLog(@"%@", userInfo);
}

場景三 多界面傳值

通知傳值
  1. 通知傳值適用于任意控制器(界面),不管兩個控制器之間是否有關聯,只需滿足一個條件,在傳值的時候必須保證通知已經被設定,即已添加通知(觀察者observer)?,F假設從詳情界面傳值到主界面,即從下一個界面傳值到上一個界面,具體實現方式如下。
  • 傳值步驟
steps 1:注冊通知:為保證在傳值時通知已經被設定,因此需要在HomeViewController.m文件中注冊通知。
#import "HomeViewController.h"
#import "DetailViewController.h"

@interface HomeViewController ()

@end

@implementation HomeViewController

- (instancetype)init {
    self = [super init];
    if (self) {

    /**
     *  注冊通知
     *
     *  @param observer 觀察者對象
     *  @param selector 觸發方法,即當收到通知之后執行的方法
     *  @param name     通知代號,即通知標識,發送通知時的標識必須和注冊通知時的標識一致
     *  @param object   是否傳值,在注冊通知的時候無需值,因此此處可填nil
     *
     */

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(respondsToNotification:) name:@"notification_name" object:nil];
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
}

#pragma mark *** responds notification ***

// 處理通知,當接收到通知的時候該方法會自動調用
// 在此處獲取從發送通知的控制器傳過來的值
- (void)respondsToNotification:(NSNotification *)info {

}
steps 2:發送通知:在DetailViewController.m文件處理返回按鈕方法中,發送通知,傳值到主界面,發送通知時的標識必須與注冊通知時的標識一致。
- (void)respondsToButton:(UIButton *)sender {

    // 發送通知:通知標識必須與注冊通知時的標識一致
    // 將需要傳遞的信息以字典形式賦給 userInfo 參數
    NSDictionary *userInfo = @{@"name":@"Charles", @"age":@(22)};
    [[NSNotificationCenter defaultCenter] postNotificationName:@"notification_name" object:nil userInfo:userInfo];

}
steps 3:處理通知:在HomeViewController.m文件處理通知方法中,獲取值。
#pragma mark *** responds notification ***

// 處理通知,在此處獲取從發送通知的控制器傳過來的值
// 注意:info參數包含兩個屬性,可通過點語法訪問。
// 1、name:為對應通知的標識
// 2、userInfo:為傳遞的信息
- (void)respondsToNotification:(NSNotification *)info {
    NSLog(@"%@", info.userInfo); 
}
steps 4:移除通知:通知在界面被釋放的時候一定記得移除,否則可能會導致程序的奔潰。移除通知在注冊通知控制器中的[dealloc]方法中實現。
- (void)dealloc
{
    // 移除通知
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
  • 注意
    1、通知傳值的使用會貫穿如下4個步驟:注冊通知 -> 發送通知 -> 處理通知 -> 移除通知
    2、通知必須先注冊再使用,通知必須在不需要的時候調用remove方法移除。
單例傳值
  1. 單例貫穿整個應用程序聲明周期,利用單例傳值適用于任何控制器,使用前提是在獲取值的時候必須保證單例屬性有值,否則獲取值為nil,此處模擬從主頁視圖控制器傳值到詳情視圖控制器。
  • 傳值步驟
steps 1:創建單例,繼承于NSObject,任意命名,必須符合規范。此處創建單例類名為Singleton。
steps 2:在Singleton.h中聲明傳值屬性,并且聲明單例類便利構造器。
@interface Singleton : NSObject

@property (nonatomic, strong) NSDictionary *userInfo; /**< 單例屬性 */

+ (instancetype)defaultSingleton; /**< 單例便利構造器 */

@end
steps 3:在Singleton.m文件中實現遍歷構造器方法。
#import "Singleton.h"

static Singleton *singleton = nil;

@implementation Singleton

+ (instancetype)defaultSingleton {

    // GCD創建單例,效率更高,性能更好,消耗更低。
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        singleton = [[Singleton alloc] init];
    });
    return singleton;
}
@end
steps 4:在HomeViewController.m文件中獲取單例實例,并且賦值單例屬性,賦值位置可根據實際情況進行調整。
// 單例屬性賦值
- (void)viewDidLoad {
    [super viewDidLoad];

    // 獲取單例實例,首先需導入Singleton.h
    Singleton *singleton = [Singleton defaultSingleton];

    // 單例屬性賦值
    NSDictionary *userInfo = @{@"name":@"Charles", @"age":@(22)};
    singleton.userInfo = userInfo;
}
steps 5:在DetailViewController.m文件中獲取單例屬性,取值位置可根據實際情況進行調整。
// 獲取單例屬性
- (void)viewDidLoad {
    [super viewDidLoad];

    // 獲取單例實例,首先需導入Singleton.h
    Singleton *singleton = [Singleton defaultSingleton];

    // 獲取單例屬性值
    NSLog(@"%@", singleton.userInfo);
}
NSUserDefaults傳值
  1. NSUserDefaults系統單例傳值和自定義單例傳值基本一致,首先需保證NSUserDefaults對應key中有值,此處模擬主頁視圖控制器傳值到詳情視圖控制器
  • 傳值步驟
steps 1:在HomeViewController.m中獲取NSUserDefaults實例,并且存值。
- (void)saveValueInUserDefaults {

    // 獲取NSUserDefaults實例
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    // 存值
    NSDictionary *userInfo = @{@"name":@"Charles", @"age":@(22)};
    [defaults setObject:userInfo forKey:@"userInfo"];

    // 同步數據
    [defaults synchronize];
}
steps 2:在DetailViewController.m中獲取值
- (void)getValueInUserDefaults {

    // 獲取NSUserDefaults實例
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    // 根據key獲取值
    NSDictionary *userInfo = [defaults objectForKey:@"userInfo"];

    NSLog(@"%@", userInfo);
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,242評論 25 708
  • 內容抽屜菜單ListViewWebViewSwitchButton按鈕點贊按鈕進度條TabLayout圖標下拉刷新...
    皇小弟閱讀 46,884評論 22 665
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,229評論 4 61
  • 會不會 有一天 憂郁成疾 死在一場深沉的痛楚里 無休無止 蔓延于血液 縱影子瘦落成鬼 游蕩飄獨的北寒中 糾纏著 滄...
    樊小四閱讀 160評論 3 8
  • 閱讀小黃書《善解童貞》第二天“戀父戀母” 《親密關系》中有一節是關于性的罪惡感的。講的是兩性之間并不能真正享受性,...
    竹筠益閱讀 1,097評論 0 2