文章目录
通知传值
通知传值是 iOS 开发中一种解耦 的传值方式,它允许没有直接引用关系的对象之间进行通信。
核心概念
什么是通知中心
NSNotificationCenter 是一个单例对象,负责管理通知的发送和接收。它像一个"广播站":
- 发送者:发布通知(不需要知道谁在监听)
- 接收者:监听通知(不需要知道谁在发送)
- 通知中心:负责转发
三个核心角色
| 角色 | 说明 | 对应方法 |
|---|---|---|
| 通知对象 | 携带信息的载体 | NSNotification |
| 观察者 | 监听通知的对象 | addObserver:selector:name:object: |
| 发布者 | 发送通知的对象 | postNotificationName:object:userInfo: |
通知的组成
NSNotification 包含三个部分:
- name: 通知名称(唯一标识)
- object: 发送通知的对象(通常是 self)
- userInfo: 传递的数据(字典)
通知的生命周期
- 观察者注册 → 2. 发送通知 → 3. 通知中心分发 → 4. 观察者回调 → 5. 移除观察者
举例讲解
VCSecond 有一个 TextField,输入文字后通过通知传给 VCFirst 的 Label 显示
创建VCFirst 和 VCSecond 两个视图控制器
给VCFirst 定义属性showLahbel用来显示传值的结果, 定义button 来通过调用事件切换视图控制器
定义通知的名称
objc
VCFirsrt.m
// 定义通知名称
static NSString * const kTextFieldNotification = @"TextFieldNotification";
@interface VCFirst ()
@property (nonatomic, strong) UILabel *showLabel;
@property (nonatomic, strong) UIButton *pushButton;
@end
定义通知名称的作用:
通知名称就像一个"频道号"或"广播频率",决定了通知发送方和接收方能否匹配上。
创建VCFirst 的Label 和 UIButton, 并注册通知监听
objc
// VCFirst.m
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"First VC";
// 创建 Label(用于显示接收的数据)
self.showLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 250, 300, 50)];
self.showLabel.text = @"等待接收文字...";
self.showLabel.textAlignment = NSTextAlignmentCenter;
self.showLabel.backgroundColor = [UIColor lightGrayColor];
self.showLabel.textColor = [UIColor blackColor];
[self.view addSubview:self.showLabel];
// 创建按钮(跳转到 Second VC)
self.pushButton = [UIButton buttonWithType:UIButtonTypeSystem];
self.pushButton.frame = CGRectMake(100, 350, 150, 44);
[self.pushButton setTitle:@"去输入文字" forState:UIControlStateNormal];
[self.pushButton addTarget:self action:@selector(pushToSecond) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.pushButton];
// 注册通知监听
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(receiveText:)
name:kTextFieldNotification
object:nil];
}
[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveText:) name:kTextFieldNotification object:nil的作用:
这是向通知中心注册一个观察者的方法调用,包含 4 个关键参数:
| 参数 | 类型 | 作用 | 本例中的值 |
|---|---|---|---|
observer |
id |
观察者对象,谁要监听通知 | self(当前对象) |
selector |
SEL |
收到通知后调用哪个方法 | @selector(receiveText:) |
name |
NSString |
监听哪个通知名称 | kTextFieldNotification |
object |
id |
限定发送者对象(过滤器) | nil(不限定) |
设置按钮事件, 创建视图控制器VCSecond 并且切换视图控制器
objc
// VCFirst.m
- (void)pushToSecond {
VCSecond *secondVC = [[VCSecond alloc] init];
[self.navigationController pushViewController:secondVC animated:YES];
}
接受通知的方法, 收到通知调用的方法, 将接受到的字符串赋值给laebl,显示出来
objc
// VCFirst.m
// 接收通知的方法
- (void)receiveText:(NSNotification *)notification {
// 从 userInfo 中取出 text
NSString *text = notification.userInfo[@"text"];
// 更新 Label
self.showLabel.text = [NSString stringWithFormat:@"收到:%@", text];
}
在对象销毁的时候移除观察者, 否则会导致野指针
objc
// 移除观察者(重要)
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
给VCSecond 定义属性inputTextField和属性 sendButton , 用来输入要传值的内容和切换视图控制器, 同时定义通知名称
objc
// VCSecond.m
#import "VCSecond.h"
// 通知名称必须和 First 中一致
static NSString * const kTextFieldNotification = @"TextFieldNotification";
@interface VCSecond ()
@property (nonatomic, strong) UITextField *inputTextField;
@property (nonatomic, strong) UIButton *sendButton;
@end
通知名称本质上是发送方和接收方之间约定的字符串 ,需要在两端保持一致, 才能实现通信
因此,需要在需要发送和接受通知的视图控制器中都定义通知名称并且保持一致
创建VCSecond 的inputField 和 sendButton
objc
// VCSecond.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"VCSecond";
// 创建TextField
self.inputTextField = [[UITextField alloc] initWithFrame: CGRectMake(50, 250, 275, 44)];
// 输入框风格
self.inputTextField.borderStyle = UITextBorderStyleRoundedRect;
self.inputTextField.placeholder = @"请输入文字";
// 编辑时显示清除按钮
self.inputTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
[self.view addSubview: _inputTextField];
// 创建发送按钮
self.sendButton = [UIButton buttonWithType: UIButtonTypeSystem];
self.sendButton.frame = CGRectMake(100, 320, 150, 44);
[self.sendButton setTitle: @"发送并返回" forState: UIControlStateNormal];
self.sendButton.backgroundColor = [UIColor systemBlueColor];
[self.sendButton setTitleColor: [UIColor whiteColor] forState: UIControlStateNormal];
[self.sendButton addTarget: self action: @selector(sendAndBack) forControlEvents: UIControlEventTouchUpInside];
[self.view addSubview: _sendButton];
}
设置按钮事件: 发送通知 并 切换视图控制器
objc
// VCSecond.m
- (void) sendAndBack {
// 获取输入的文字
NSString* str = self.inputTextField.text;
// 如果文字为空, 给定默认值
if (str.length == 0) {
str = @"空消息";
}
// 发送通知
[[NSNotificationCenter defaultCenter] postNotificationName: kTextFieldNotification object: self userInfo: @{@"text": str}];
// 返回上一个界面
[self.navigationController popViewControllerAnimated: YES];
}
发送通知:
[[NSNotificationCenter defaultCenter] postNotificationName: kTextFieldNotification object: self userInfo: @{@"text": str}]; 这段代码实现了发送通知的功能
-
[NSNotificationCenter defaultCenter]获取通知中心的单例, -
[NSNotificationCenter defaultCenter]: 通知的名称 -
object: 发送者
-
userInfo: 携带的数据, 这里是一个字典, 可以传递多个数据, 例如:
objc// 传递多个数据 userInfo: @{ @"text": str, @"color": [UIColor redColor], @"number": @100 }
通知发送的对象
发送的消息是 NSNotification对象,
objc
// postNotificationName:object:userInfo: 方法签名
- (void)postNotificationName:(NSNotificationName)name
object:(nullable id)object
userInfo:(nullable NSDictionary *)userInfo;
// 参数说明:
// name: 通知名称(字符串)
// object: 发送者对象(任意对象)
// userInfo: 数据字典(NSDictionary)
在接收消息的时候通过 userInfo 属性取字典
objc
// 通过 userInfo 属性取字典
- (void)handleNotification:(NSNotification *)notification {
NSString *text = notification.userInfo[@"text"];
}