1、页面跳转
由 ViewController 页面跳转至 NextViewController 页面
(1)ViewController
- ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
- ViewController.m
#import "ViewController.h"
#import "NextViewController.h"
@interface ViewController ()
@property (nonatomic, strong) UILabel *label;
@property (nonatomic, strong) UIButton *button;
@end
@implementation ViewController
//懒加载 UILabel
-(UILabel *) label{
if (_label == nil) {
_label = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 200, 50)];
_label.backgroundColor = [UIColor blackColor];
_label.textColor = [UIColor whiteColor];
_label.font = [UIFont systemFontOfSize:20];
}
return _label;
}
//懒加载 UIButton
-(UIButton *) button{
if (_button == nil) {
_button = [[UIButton alloc]initWithFrame:CGRectMake(100, 200, 200, 50)];
_button.backgroundColor = [UIColor redColor];
//setTitle:forState: 是 UIButton 的方法,允许你为按钮的不同状态设置不同的标题
//为按钮在 普通状态 (UIControlStateNormal) 下设置标题为 "跳转至下个页面"
[_button setTitle:@"跳转至下个页面" forState:UIControlStateNormal];
//setTitleColor:forState: 是 UIButton 的方法,允许你为不同状态下的按钮标题设置不同的颜色
//为按钮在 触摸抬起 (UIControlEventTouchUpInside) 事件时,设置标题颜色为白色 ([UIColor whiteColor])
[_button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
//点击事件
//addTarget:action:forControlEvents:
//target: 触发事件时的目标对象。通常是 self,即当前类的实例
//action: 事件触发时调用的方法的 选择器,通过 @selector 来指定方法
//forControlEvents: 指定触发事件的类型
//UIControlEventTouchUpInside 按钮的 触摸抬起 事件
[_button addTarget:self action:@selector(zlzButtonClick) forControlEvents:UIControlEventTouchUpInside];
}
return _button;
}
//按钮点击事件
-(void)zlzButtonClick{
NextViewController *nextVC = [[NextViewController alloc]init];
//NextViewController 需要全屏展示
nextVC.modalPresentationStyle = UIModalPresentationFullScreen;
//presentViewController:animated:completion:
//viewControllerToPresent: 需要展示的视图控制器
//animated: 是否使用动画过渡
//completion: 动画完成后的回调,可以是 nil
[self presentViewController:nextVC animated:YES completion:nil];
}
/**
• viewDidLoad:视图加载后,初始化视图。
• viewWillAppear::视图即将显示,准备更新 UI。
• viewDidAppear::视图已显示,启动交互或动画。
• viewWillDisappear::视图即将隐藏,保存数据。
• viewDidDisappear::视图已隐藏,释放资源或暂停任务。
**/
//视图加载
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor greenColor];
NSLog(@"First viewDidLoad");
//添加控件至根View
[self.view addSubview:self.label];
[self.view addSubview:self.button];
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
NSLog(@"------First viewWillAppear");
}
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
NSLog(@"------First viewWillLayoutSubviews");
}
- (void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
NSLog(@"------First viewDidLayoutSubviews");
}
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
NSLog(@"------First viewDidAppear");
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
NSLog(@"------First viewWillDisappear");
}
- (void)viewDidDisappear:(BOOL)animated{
NSLog(@"------First viewDidDisappear");
}
@end
(2)NextViewController
- NextViewController.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface NextViewController : UIViewController
@end
NS_ASSUME_NONNULL_END
- NextViewController.m
#import "NextViewController.h"
@interface NextViewController ()
@property (strong, nonatomic) UITextField *textFiled;
@property (strong, nonatomic) UIButton *button;
@end
@implementation NextViewController
-(UITextField *)textFiled{
if (_textFiled == nil) {
_textFiled = [[UITextField alloc]initWithFrame:CGRectMake(100, 300, 200, 50)];
_textFiled.textColor = [UIColor blackColor];
_textFiled.borderStyle = UITextBorderStyleLine;
}
return _textFiled;
}
-(UIButton *) button{
if (_button == nil) {
_button = [[UIButton alloc]initWithFrame:CGRectMake(100, 400, 200, 50)];
_button.backgroundColor = [UIColor redColor];
[_button setTitle:@"返回上一个页面" forState:UIControlStateNormal];
[_button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
//点击事件
[_button addTarget:self action:@selector(zlzBackClick) forControlEvents:UIControlEventTouchUpInside];
}
return _button;
}
-(void)zlzBackClick{
// dismissViewControllerAnimated:animated:completion:
//用来 关闭当前视图控制器 的方法,通常用于关闭通过 presentViewController:animated:completion: 模态展示的视图控制器
//completion:nil:表示关闭完成后执行的回调
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"------Second viewDidLoad");
self.view.backgroundColor = [UIColor yellowColor];
[self.view addSubview:self.textFiled];
[self.view addSubview:self.button];
}
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
NSLog(@"------Second viewWillAppear");
}
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
NSLog(@"------Second viewWillLayoutSubviews");
}
- (void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
NSLog(@"------Second viewDidLayoutSubviews");
}
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
NSLog(@"------Second viewDidAppear");
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
NSLog(@"------Second viewWillDisappear");
}
- (void)viewDidDisappear:(BOOL)animated{
NSLog(@"------Second viewDidDisappear");
}
@end
2、界面传值
2.1、属性传值
- 在 NextViewController.h 添加属性 str
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface NextViewController : UIViewController
//属性传值
@property (nonatomic, strong) NSString *str;
@end
NS_ASSUME_NONNULL_END
- 在 ViewController.m 的跳转点击事件中 为NextViewController中的属性str 赋值
//按钮点击事件
-(void)zlzButtonClick{
NextViewController *nextVC = [[NextViewController alloc]init];
//NextViewController 需要全屏展示
nextVC.modalPresentationStyle = UIModalPresentationFullScreen;
//属性传值---传递
nextVC.str = @"属性传值";
//presentViewController:animated:completion:
//viewControllerToPresent: 需要展示的视图控制器
//animated: 是否使用动画过渡
//completion: 动画完成后的回调,可以是 nil
[self presentViewController:nextVC animated:YES completion:nil];
}
- 在 NextViewController.m 中 textFiled 懒加载时赋值
-(UITextField *)textFiled{
if (_textFiled == nil) {
_textFiled = [[UITextField alloc]initWithFrame:CGRectMake(100, 300, 200, 50)];
_textFiled.textColor = [UIColor blackColor];
_textFiled.borderStyle = UITextBorderStyleLine;
//属性传值---接收并显示
_textFiled.text = self.str;
}
return _textFiled;
}
- 效果
2.2、单例传值
(1)创建单例
-
DefaultInstance.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface DefaultInstance : NSObject
+(instancetype)getInstance;
@property (nonatomic, strong) NSString *instanceStr;
@end
NS_ASSUME_NONNULL_END
-
DefaultInstance.m
#import "DefaultInstance.h"
@implementation DefaultInstance
//类方法---创建单例对象
+(instancetype)getInstance{
//首次创建会 将 sharedVC 赋值为 nil,然后创建一个对象
//非首次都会直接返回上次的值
static DefaultInstance *instance = nil;
if (instance == nil) {
instance = [[DefaultInstance alloc]init];
}
return instance;
}
@end
(2)正向传值
- 在 ViewController.m 的跳转点击事件,为单例的属性值赋值
//按钮点击事件
-(void)zlzButtonClick{
NextViewController *nextVC = [[NextViewController alloc]init];
//NextViewController 需要全屏展示
nextVC.modalPresentationStyle = UIModalPresentationFullScreen;
//单例传值---正向传递
[DefaultInstance getInstance].instanceStr = @"单例传值";
//presentViewController:animated:completion:
//viewControllerToPresent: 需要展示的视图控制器
//animated: 是否使用动画过渡
//completion: 动画完成后的回调,可以是 nil
[self presentViewController:nextVC animated:YES completion:nil];
}
- 在 NextViewController.m 的 textFiled懒加载时赋值
-(UITextField *)textFiled{
if (_textFiled == nil) {
_textFiled = [[UITextField alloc]initWithFrame:CGRectMake(100, 300, 200, 50)];
_textFiled.textColor = [UIColor blackColor];
_textFiled.borderStyle = UITextBorderStyleLine;
//单例传值---接收并显示
_textFiled.text = [DefaultInstance getInstance].instanceStr;
}
return _textFiled;
}
- 效果
(3)反向传值
- 在 NextViewController.m 的返回点击事件中,为单例中的属性赋值
-(void)zlzBackClick{
//单例传值---反向传递
NSLog(@"单例传值---反向传递: %@",self.textFiled.text);
[DefaultInstance getInstance].instanceStr = self.textFiled.text;
// dismissViewControllerAnimated:animated:completion:
//用来 关闭当前视图控制器 的方法,通常用于关闭通过 presentViewController:animated:completion: 模态展示的视图控制器
//completion:nil:表示关闭完成后执行的回调
[self dismissViewControllerAnimated:YES completion:nil];
}
- 在 ViewController.m 的 viewWillAppear() 方法中,获取单例属性值并展示
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
NSLog(@"------First viewWillAppear");
//单例传值---反向接收并展示
NSLog(@"单例传值---反向接收并展示:%@", [DefaultInstance getInstance].instanceStr);
self.label.text = [DefaultInstance getInstance].instanceStr;
}
- 效果
2.3、NSUserDefaults传值
NSUserDefaults传值与单例传值类似,区别是单例传值是在内存中创建单例,而NSUserDefaults 则是在磁盘文件中的。
(1)正向传值
- 在 ViewController.m 中的跳转点击事件中将值写入文件
//按钮点击事件
-(void)zlzButtonClick{
NextViewController *nextVC = [[NextViewController alloc]init];
//NextViewController 需要全屏展示
nextVC.modalPresentationStyle = UIModalPresentationFullScreen;
//NSUserDefaults-正向传值(存入磁盘文件)
[[NSUserDefaults standardUserDefaults] setObject:@"NSUserDefaults传值" forKey:@"zlzKey"];
//写入
[[NSUserDefaults standardUserDefaults] synchronize];
//presentViewController:animated:completion:
//viewControllerToPresent: 需要展示的视图控制器
//animated: 是否使用动画过渡
//completion: 动画完成后的回调,可以是 nil
[self presentViewController:nextVC animated:YES completion:nil];
}
- 在 NextViewController.m 的 textFiled 懒加载时赋值
-(UITextField *)textFiled{
if (_textFiled == nil) {
_textFiled = [[UITextField alloc]initWithFrame:CGRectMake(100, 300, 200, 50)];
_textFiled.textColor = [UIColor blackColor];
_textFiled.borderStyle = UITextBorderStyleLine;
//NSUserDefaults传值---接受并显示(从磁盘文件中读取)
_textFiled.text = [[NSUserDefaults standardUserDefaults] objectForKey:@"zlzKey"];
}
return _textFiled;
}
- 效果
(2)反向传值
- 在 NextViewController.m 中的返回点击事件中将值写入文件
-(void)zlzBackClick{
//NSUserDefaults传值---反向传递
NSLog(@"NSUserDefaults传值---反向传递:%@", self.textFiled.text);
[[NSUserDefaults standardUserDefaults] setObject:self.textFiled.text forKey:@"zlzBackKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
// dismissViewControllerAnimated:animated:completion:
//用来 关闭当前视图控制器 的方法,通常用于关闭通过 presentViewController:animated:completion: 模态展示的视图控制器
//completion:nil:表示关闭完成后执行的回调
[self dismissViewControllerAnimated:YES completion:nil];
}
- 在 ViewController.m 中的 viewWillAppear() 方法中获取文件中的值
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
NSLog(@"------First viewWillAppear");
//NSUserDefaults传值---反向接收并展示
NSLog(@"NSUserDefaults---反向接收并展示:%@", [[NSUserDefaults standardUserDefaults] objectForKey:@"zlzBackKey"]);
self.label.text = [[NSUserDefaults standardUserDefaults] objectForKey:@"zlzBackKey"];
}
- 效果
2.4、代理传值
- 代理传值主要应用于反向传值,即本示例中 NextViewController -> ViewController 传值
- 委托方:NextViewController
- 代理方:ViewController
(1)委托方 NextViewController 定义协议
- 在 NextViewController.h 中创建协议
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
//委托方定义协议
@protocol zlzPassValueDelegate <NSObject>
//协议定义一个方法
-(void)passValue:(NSString*)value;
@end
@interface NextViewController : UIViewController
//属性传值
@property (nonatomic, strong) NSString *str;
//定义一个持有协议的id指针
//weak是为了防止指针循环引用
@property (weak)id<zlzPassValueDelegate> zlzDelegate;
@end
NS_ASSUME_NONNULL_END
- 在 NextViewController.m 中调用协议方法
-(void)zlzBackClick{
//代理传值---反向传递
[self.zlzDelegate passValue:self.textFiled.text];
// dismissViewControllerAnimated:animated:completion:
//用来 关闭当前视图控制器 的方法,通常用于关闭通过 presentViewController:animated:completion: 模态展示的视图控制器
//completion:nil:表示关闭完成后执行的回调
[self dismissViewControllerAnimated:YES completion:nil];
}
(2)代理方 ViewController 实现协议方法
- 在 ViewController.m 中实现协议方法
#import "ViewController.h"
#import "NextViewController.h"
@interface ViewController ()<zlzPassValueDelegate> //遵守协议
@property (nonatomic, strong) UILabel *label;
@property (nonatomic, strong) UIButton *button;
@end
@implementation ViewController
//...省略部分代码
//代理传值---实现协议方法
-(void)passValue:(NSString *)value{
self.label.text = value;
}
@end
(3)绑定代理关系
- 在 ViewController.m 的跳转点击事件中,设置 NextViewController 的代理是自己
//按钮点击事件
-(void)zlzButtonClick{
NextViewController *nextVC = [[NextViewController alloc]init];
//NextViewController 需要全屏展示
nextVC.modalPresentationStyle = UIModalPresentationFullScreen;
//代理传值---设置代理关系
nextVC.zlzDelegate = self;
//presentViewController:animated:completion:
//viewControllerToPresent: 需要展示的视图控制器
//animated: 是否使用动画过渡
//completion: 动画完成后的回调,可以是 nil
[self presentViewController:nextVC animated:YES completion:nil];
}
2.5、block传值
block传值与代理传值有点类似,也是主要应用于反向传值,但是使用起来比代理传值要简单。
- 在 NextViewController.h 中定义 block
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface NextViewController : UIViewController
//属性传值
@property (nonatomic, strong) NSString *str;
// 定义一个 block 进行页面反向传值
//copy属性是为了防止 block 循环引用
//block就是一个属性
//^就是block的标志
@property (copy) void (^zlzBlock)(NSString*);
@end
NS_ASSUME_NONNULL_END
- 在 NextViewController.m 中的返回点击事件中调用 block 方法
-(void)zlzBackClick{
//block传值---反向传递
self.zlzBlock(self.textFiled.text);
// dismissViewControllerAnimated:animated:completion:
//用来 关闭当前视图控制器 的方法,通常用于关闭通过 presentViewController:animated:completion: 模态展示的视图控制器
//completion:nil:表示关闭完成后执行的回调
[self dismissViewControllerAnimated:YES completion:nil];
}
- 在 ViewController.m 中的跳转点击事件中实现 属性 block
-(void)zlzButtonClick{
NextViewController *nextVC = [[NextViewController alloc]init];
//NextViewController 需要全屏展示
nextVC.modalPresentationStyle = UIModalPresentationFullScreen;
//block传值---实现block-接收来自页面2的值
nextVC.zlzBlock = ^(NSString *value){
self.label.text = value;
};
//presentViewController:animated:completion:
//viewControllerToPresent: 需要展示的视图控制器
//animated: 是否使用动画过渡
//completion: 动画完成后的回调,可以是 nil
[self presentViewController:nextVC animated:YES completion:nil];
}
2.6、通知传值
通知传值更灵活,主要用于跨页面跳转时。
类似于Android中的广播。
(1)接收方 ViewController
- 在 ViewController.m 的跳转点击事件中,设置通知监听
-(void)zlzButtonClick{
NextViewController *nextVC = [[NextViewController alloc]init];
//NextViewController 需要全屏展示
nextVC.modalPresentationStyle = UIModalPresentationFullScreen;
//通知传值---添加监听,等待页面2的传值
//addObserver:self 添加监听者为自己
//通知的名称zlzNotify
//object:nil 表示所有的发送者,只要是名为zlzNotify通知的都监听接收
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dealWithNotify:) name:@"zlzNotify" object:nil];
//presentViewController:animated:completion:
//viewControllerToPresent: 需要展示的视图控制器
//animated: 是否使用动画过渡
//completion: 动画完成后的回调,可以是 nil
[self presentViewController:nextVC animated:YES completion:nil];
}
//接收到通知后的处理---参数1:通知
-(void)dealWithNotify:(NSNotification*)notification{
self.label.text = notification.userInfo[@"zlzNotificationKey"];
}
(2)发送方 NextViewController
- 在 NextViewController.m 的返回点击事件中发送通知
-(void)zlzBackClick{
//通知传值---发送通知
//object:nil表示群发
[[NSNotificationCenter defaultCenter]postNotificationName:@"zlzNotify" object:nil userInfo:@{@"zlzNotificationKey":self.textFiled.text}];
// dismissViewControllerAnimated:animated:completion:
//用来 关闭当前视图控制器 的方法,通常用于关闭通过 presentViewController:animated:completion: 模态展示的视图控制器
//completion:nil:表示关闭完成后执行的回调
[self dismissViewControllerAnimated:YES completion:nil];
}
3、总结
属性传值 | 简单的正向传值,不能跨页面传值 |
单例传值 | 可以正向反向传值,可以跨页面,但是需要创建一个单例对象 |
NSUserDefaults传值 | 类似单例传值,区别是单例传值是把值写入内存,而它是把值写入沙盒文件 |
代理传值 | 主要用于反向传值,一对一,必须两个页面建立代理关系 |
block传值 | 主要用于反向传值,一对一 代理传值能做的它都能做,但他不能取代代理传值 |
通知传值 | 可以跨页面传值,多对多 |