美文网首页
UI界面传值

UI界面传值

作者: misakatao | 来源:发表于2017-06-21 14:25 被阅读11次

传值需求

  • 将用户信息 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)。现假设从详情界面传值到主界面,即从下一个界面传值到上一个界面,具体实现方式如下。
  • 传值步骤
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);
}

相关文章

  • UI总结-界面传值

    UI总结-界面传值(属性传值,协议传值,block传值,通知中指传值) 在编程过程中,界面传值是很重要的一部分,常...

  • UI界面传值

    传值需求 将用户信息 userInfo 作为传值对象进行传递。 场景一 主页传值到详情页 现在模拟传递用户名:us...

  • iOS中界面传值的几种方式

    1.属性传值 属性传值适用于顺序传值,从前面的界面传值给后面的界面。 2.代理传值 用代理的方式实现界面间传值稍微...

  • IOS开发 多界面传值

    本节学习内容: 1.多界面传值的基本概念 2.多界面传值的方法 3.多界面传值的应用 【多界面传值 属性】 cha...

  • ios界面传值2016.5

    五种方法 1.属性传值,适合界面A到界面B的传值2.单例, 多个界面传值3.通知 , 界面A跳...

  • iOS开发-属性、block、代理、通知传值

    传值在开发中我们会经常用到,传值又分为正向传值和反向传值。从界面一跳转到界面二且将值从界面一传递给界面二使用,称之...

  • iOS 属性、代理、通知、Block传值

    实际开发中,几乎到处都会有用到传值,而传值分为正向传值以及逆(反)向传值,比如从界面一调到界面二,并将值从界面一传...

  • swift中的协议代理传值

    协议代理传值一般使用在下级界面往上级界面传值的情况,这里将上级界面设定为A界面,下级界面设定为B界面。传值的具体操...

  • iOS的5种传值

    (-)属性传值 属性传值(场景)一般用于正向传值,即第一个界面传值给第二个界面 属性传值是这几大传值中最简单的传值...

  • UI总结-tableView的界面传值

    UI总结-tableView的界面传值 因为tableView在以后的开发占了很重要的地位,所以把table...

网友评论

      本文标题:UI界面传值

      本文链接:https://www.haomeiwen.com/subject/pettcxtx.html