学习了关于iOS开发中界面传值的基本用法,记录下笔记。
学习阶段,如果哪部分有问题,欢迎指正,共同探讨。@Apach3
iOS中几种常见的传值方式:
(1)属性传值:正向传值,只能从a界面跳转到b传值。
(2)单例传值:将数据储存到内存,然后读内存达到传值目的,可以实现正向、反向、跨页面传值。
(3)NSUserDefaults传值:将数据储存到文件,然后读文件达到传值目的,可以实现正向、反向、跨页面传值。
(4)代理传值:委托方->delegate通讯->代理方,委托方->持有协议、调用协议方法->协议,协议->遵守协议、实现协议方法->代理方。
(5)block传值:不像代理那么麻烦,设置简单,苹果主推,和代理传值一样适用于反向传值,有直接跳转关系的传值。
(6)通知传值:使用灵活,适用于跨页面传值。先在接收方定义观察者,等待通知中心发出的消息,然后由发送方发送到通知中心,通知中心拿到数据再回调给接收方。
代码实现六种传值:
ViewController.m:
#import "ViewController.h"
#import "NextViewController.h"
#import "DefaultInstance.h"
/*
代理传值 - 遵守协议
*/
@interface ViewController () <valueDelegate>
@property (nonatomic, strong) UIButton *nextVCButton;
@property (nonatomic, strong) UILabel *textLabel;
@property (nonatomic, strong) UILabel *showLabel;
@end
@implementation ViewController
- (UIButton *)nextVCButton {
if (!_nextVCButton) {
_nextVCButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_nextVCButton setTitle:@"点击跳到下个页面传值" forState:UIControlStateNormal];
[_nextVCButton setFrame:CGRectMake((self.view.frame.size.width-200)/2, 200, 200, 30)];
[_nextVCButton setBackgroundColor:[UIColor grayColor]];
[_nextVCButton addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _nextVCButton;
}
- (UILabel *)textLabel {
if (!_textLabel) {
_textLabel = [[UILabel alloc] initWithFrame:CGRectMake((self.view.frame.size.width-200)/2, 250, 200, 30)];
_textLabel.text = @"这是第一个页面";
_textLabel.backgroundColor = [UIColor redColor];
_textLabel.textColor = [UIColor whiteColor];
_textLabel.font = [UIFont boldSystemFontOfSize:25];
_textLabel.textAlignment = NSTextAlignmentCenter;
}
return _textLabel;
}
- (UILabel *)showLabel {
if (!_showLabel) {
_showLabel = [[UILabel alloc] initWithFrame:CGRectMake((self.view.frame.size.width-200)/2, 300, 200, 30)];
_showLabel.backgroundColor = [UIColor orangeColor];
_showLabel.textColor = [UIColor whiteColor];
_showLabel.font = [UIFont boldSystemFontOfSize:15];
_showLabel.textAlignment = NSTextAlignmentCenter;
}
return _showLabel;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.view addSubview:self.nextVCButton];
[self.view addSubview:self.textLabel];
[self.view addSubview:self.showLabel];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
/*
单例传值 - 反向接收
*/
_showLabel.text = [DefaultInstance sharedInstance].string;
/*
NSUserDefaults传值 - 反向接收
*/
_showLabel.text = [[NSUserDefaults standardUserDefaults] objectForKey:@"fanxiang"];
}
- (void)buttonClick:(id)sender {
NextViewController *nextVC = [[NextViewController alloc] init];
/*
属性传值 - 传递
*/
nextVC.string = @"属性传值 - 收到了";
/*
单例传值 - 传递
*/
[DefaultInstance sharedInstance].string = @"单例传值 - 收到了";
/*
NSUserDefaults传值 - 传递
*/
[[NSUserDefaults standardUserDefaults] setObject:@"NSUserDefaults传值" forKey:@"NSUserDefaults"]; //写数据到文件
[[NSUserDefaults standardUserDefaults] synchronize]; //同步数据
/*
代理传值 - 设置代理关系
*/
nextVC.delegate = self;
/*
block传值 - 实现block,接受数据
*/
nextVC.block = ^(NSString *string) {
_showLabel.text = string;
};
/*
通知传值 - 添加监听,等待传值
*/
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notifiHandle:) name:@"notifi" object:nil];
[self presentViewController:nextVC animated:YES completion:nil];
}
/*
代理传值 - 实现协议方法,接受来自页面的值
*/
- (void)passValue:(NSString *)string {
_showLabel.text = string;
}
/*
通知传值 - 接收到通知之后的处理
*/
- (void)notifiHandle:(NSNotification *)notifi {
_showLabel.text = notifi.userInfo[@"notifi"];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
NextViewController.h:
#import <UIKit/UIKit.h>
/*
代理传值 - 委托方创建一个协议
*/
@protocol valueDelegate <NSObject>
- (void)passValue:(NSString *)string;
@end
@interface NextViewController : UIViewController
@property (nonatomic, strong) UIButton *button;
@property (nonatomic, strong) UILabel *textLabel;
@property (nonatomic, strong) UILabel *showLabel;
/*
属性传值 - 属性
*/
@property (nonatomic, strong) NSString *string;
/*
代理传值 - 定义一个持有协议的id指针
*/
//@property (weak)id<valueDelegate>delegete;
@property (nonatomic, weak) id<valueDelegate> delegate;
/*
block传值 - 定义(返回值类型(block名字)block参数)
*/
@property (nonatomic, copy) void (^block)(NSString *);
@end
NextViewController.m:
#import "NextViewController.h"
#import "DefaultInstance.h"
@interface NextViewController ()
@end
@implementation NextViewController
- (UIButton *)button {
if (!_button) {
_button = [UIButton buttonWithType:UIButtonTypeCustom];
[_button setTitle:@"点击跳回上个页面传值" forState:UIControlStateNormal];
[_button setFrame:CGRectMake((self.view.frame.size.width-200)/2, 200, 200, 30)];
[_button setBackgroundColor:[UIColor grayColor]];
[_button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _button;
}
- (UILabel *)textLabel {
if (!_textLabel) {
_textLabel = [[UILabel alloc] initWithFrame:CGRectMake((self.view.frame.size.width-200)/2, 250, 200, 30)];
_textLabel.text = @"这是第二个页面";
_textLabel.backgroundColor = [UIColor redColor];
_textLabel.textColor = [UIColor whiteColor];
_textLabel.font = [UIFont boldSystemFontOfSize:25];
_textLabel.textAlignment = NSTextAlignmentCenter;
}
return _textLabel;
}
- (UILabel *)showLabel {
if (!_showLabel) {
_showLabel = [[UILabel alloc] initWithFrame:CGRectMake((self.view.frame.size.width-200)/2, 300, 200, 30)];
_showLabel.backgroundColor = [UIColor orangeColor];
_showLabel.textColor = [UIColor whiteColor];
_showLabel.font = [UIFont boldSystemFontOfSize:15];
_showLabel.textAlignment = NSTextAlignmentCenter;
}
return _showLabel;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.button];
[self.view addSubview:self.textLabel];
[self.view addSubview:self.showLabel];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
/*
属性传值 - 接收
*/
_showLabel.text = _string;
/*
单例传值 - 接收
*/
_showLabel.text = [DefaultInstance sharedInstance].string;
/*
NSUserDefaults传值 - 接收
*/
_showLabel.text = [[NSUserDefaults standardUserDefaults] objectForKey:@"NSUserDefaults"];
}
- (void)buttonClick:(id)sender {
/*
单例传值 - 反向传递
*/
[DefaultInstance sharedInstance].string = @"单例传值 - 反向传递 - 收到了";
/*
NSUserDefaults传值 - 反向传递
*/
[[NSUserDefaults standardUserDefaults] setObject:@"NSUserDefaults反向传值" forKey:@"fanxiang"];
[[NSUserDefaults standardUserDefaults] synchronize];
/*
代理传值 - 反向传递
*/
[self.delegate passValue:@"代理传值 - 收到了"];
/*
block传值 - 反向传递
*/
self.block(@"block传值 - 收到了");
/*
通知传值 - 发送通知
*/
[[NSNotificationCenter defaultCenter] postNotificationName:@"notifi" object:nil userInfo:@{@"notifi":@"通知传值 - 收到了"}];
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
DefaultInstance.h:
#import <Foundation/Foundation.h>
@interface DefaultInstance : NSObject
@property (nonatomic, strong) NSString *string;
+ (instancetype)sharedInstance;
@end
DefaultInstance.m:
/*
单例类
*/
#import "DefaultInstance.h"
@implementation DefaultInstance
/*
使用静态变量通过类方法创建单例对象
*/
+ (instancetype)sharedInstance {
static DefaultInstance *sharedVC = nil;
if (sharedVC == nil) {
sharedVC = [[DefaultInstance alloc] init];
}
return sharedVC;
}
@end
模拟器图片:
图片为NSUserDefaults传值的截图。
总结:
各个传值方式应用不同的场景,各有各的优缺点。代理传值和block传值尤其重要,需要根据自己的理解,多写多练才能熟练掌握。
加油!