OCiOS开发:界面传值
来源:互联网 发布:sai软件免费下载 编辑:程序博客网 时间:2024/06/18 13:13
引言
- 在iOS开发过程中,界面传值无处不在,可以说界面传值在iOS开发过程中是非常重要的,而传值方式也多种多样,如下我将结合几种场景介绍几种常用的界面传值方式。
传值需求
- 将用户信息 userInfo 作为传值对象进行传递。
场景一 主页传值到详情页
- 现在模拟传递用户名:
userName
。
属性传值
属性传值一般用于从主页传值到详情页。
传值步骤:
steps 1:在DetailViewController.h
文件中将需要获取的值声明成属性。
#import <UIKit/UIKit.h>@interface DetailViewController : UIViewController@property (nonatomic, strong)NSDictionary *userInfo; /**< 用户信息 */@end
steps 2:在HomeViewController.m
文件中导入头文件“DetailViewController.h”
,然后在界面跳转逻辑处理方法中初始化DetailViewController
,并通过点语法给属性userInfo赋需要传递的值。
- (void)respondsToButton:(UIButton *)sender { // 初始化详情视图控制器 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传值
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)(NSDictionary *info);@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方面的调用;
协议传值
协议传值又称代理传值,可直接将需要传递的值从委托方传送至代理人,协议传值可用于从下一个视图控制器传值到上一个视图控制器(详情页传值到主页),现假定主页是详情页的代理。
传值步骤:
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);}
场景三 多界面传值
通知传值
通知传值适用于任意控制器(界面),不管两个控制器之间是否有关联,只需满足一个条件,在传值的时候必须保证通知已经被设定,即已添加通知(观察者
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
方法移除。
单例传值
单例贯穿整个应用程序声明周期,利用单例传值适用于任何控制器,使用前提是在获取值的时候必须保证单例属性有值,否则获取值为
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传值
-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);}
- OCiOS开发:界面传值
- OCiOS开发:延迟调用
- OCiOS开发:NSURLConnection 网络请求
- OCiOS开发:录音与音效
- OCiOS开发:集合视图 UICollectionView
- OCiOS开发:绘图与曲线
- OCiOS开发:汉字转拼音
- OCiOS开发:CAGradientLayer 渐变色
- OCiOS开发:NSURLSession 网络请求
- OCiOS开发:地图与定位
- OCiOS开发:音频播放器 AVAudioPlayer
- OCiOS开发:媒体播放器 AVPlayer 与 AVPlayerViewController
- OCiOS开发:使用相册、照相机和录像
- OCiOS开发:Masonry的安装与使用
- OCiOS开发:多线程与消息通知
- OCiOS开发:手动创建CoreData数据模型
- OCiOS开发:数据持久化之属性列表、归档、NSUserDefaults
- OCiOS开发:UIKit 力学(UIDynamics)(一)
- 左右手坐标系区别和联系
- 2.2 视图的基本概念
- hive命令行不打印日志
- 2.3 视图的层次关系
- Linux各个目录含义
- OCiOS开发:界面传值
- UVA_10911_FormingQuizTeams
- 2.4 UIView的基本属性和自定义
- 大端、小端
- Windows 下Nexus搭建Maven私服
- 决策树模型入门学习
- 2.6 UIView的ContentMode
- Limit优化
- 2.7 UIView动画简单示例