【iOS】—— 通知传值

什么是通知?

通知中心传值,可以跨越多个页面传值, 一般也是从后面的页面传给前面的页面。

通知传值的步骤

通知传值可分为三个步骤:

一.在发送者(视图二)中实现一个方法进行发送通知。
[[NSNotificationCenter defaultCenter] postNotificationName:@"TransDataNoti" object:nil userInfo:_dictionary];
 //postNotificationName:之后的参数就是这个通知的名字,要和要和接收者中的名字一样,才能让接收者正确接收。     
 //object:接收对象。
 //userInfo: 携带的参数,为字典类型的数据,在例子中我携带了一个字典,因为有时候我们要传递的参数不只是一个,所以把东西全部放在通知里面,在接收者中,根据字典里面的键来取出里面的值。
 //_dictionary是我之前定义的一个字典实例。
二.在接收者(视图一)中注册通知,也就是接收者要进行接收通知,接收通知和发送通知的名字要一致。
//注册通知,用于接收通知,接收通知的名称必须和发送通知的名称保持一致才能接收到,否则无法接收到发出的通知
  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notiReceived:) name:@"TransDataNoti" object:nil];
  //注:务必让接收者中name后面的参数和发送者中的name后面的参数一样。
三.在接收者(视图一)中实现通知中的方法。
    // 参数类型是NSNotification
- (void)notiReceived:(NSNotification*)sender {
    self.textField.text = sender.userInfo[@"content"];
    self.label.text = sender.userInfo[@"content"];
}
四.在不用的时候移除通知。
- (void)dealloc {
    //移除所有通知
//    [[NSNotificationCenter defaultCenter] removeObserver:self];
    
    //移除某个通知
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"TransDataNoti" object:nil];
}

注意参数Observer为要删除的观察者,一定不能置为nil。
如果为nil它会报警告:

Null passed to a callee that requires a non-null argument。

iOS9以上对其不进行移除处理不会崩溃,但是如果这个对象是在监听一个单例对象的属性的话,在其他地方,又修改该属性,还是会崩溃。

界面传值的小实例

  • 发送者(视图二)的NewViewController.h
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface NewViewController : UIViewController<UITextFieldDelegate>

@property (nonatomic, strong) UIButton *back;
@property (nonatomic, strong) UITextField *textField;
@property (nonatomic, copy) NSMutableDictionary *dictionary;

@end

NS_ASSUME_NONNULL_END
  • 发送者(视图二)的NewViewController.m
#import "NewViewController.h"

@interface NewViewController ()

@end

@implementation NewViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor whiteColor];
    
    self.title = @"子界面";
    
    _back = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    _back.frame = CGRectMake(200, 300, 50, 40);
    [_back setTitle:@"返回" forState:UIControlStateNormal];
    [_back addTarget:self action:@selector(back:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_back];
    
    _textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 400, 250, 50)];
    _textField.keyboardType = UIKeyboardTypeDefault;
    _textField.borderStyle = UITextBorderStyleRoundedRect;
    _textField.delegate = self;
    [self.view addSubview:_textField];
    
}

//协议事件,textField结束编辑的时候执行
- (void)textFieldDidEndEditing:(UITextField *)textField {
    NSString *string = [[NSString alloc] initWithString:_textField.text];
    _dictionary = [[NSMutableDictionary alloc] init];
    [_dictionary setObject:string forKey:@"content"];
}

//按钮事件
- (void)back:(UIButton*)button {
    //发送通知回传数据,回传的数据格式自定义,这里定义为dictionary类型
    [[NSNotificationCenter defaultCenter] postNotificationName:@"TransDataNoti" object:nil userInfo:_dictionary];
    [self dismissViewControllerAnimated:YES completion:nil];
}

//点击空白处键盘回收,同时结束textField编辑
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [_textField endEditing:YES];
}
@end
  • 接收者(视图一)的ViewController.h
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController<UITextFieldDelegate>

@property (nonatomic, strong) UIButton *button;
@property (nonatomic, strong) UITextField *textField;
@property (nonatomic, strong) UILabel *label;

@end
  • 接收者(视图一)的ViewController.m
#import "ViewController.h"
#import "NewViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    self.title = @"主界面";
    
    _button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [_button setTitle:@"跳转" forState:UIControlStateNormal];
    [_button addTarget:self action:@selector(jump:) forControlEvents:UIControlEventTouchUpInside];
    _button.frame = CGRectMake(100, 200, 60, 30);
    [self.view addSubview:_button];
    
    _label = [[UILabel alloc] init];
    _label.text = @"通知";
    _label.frame = CGRectMake(200, 300, 100, 40);
    [self.view addSubview:_label];
    
    _textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 400, 250, 50)];
    _textField.keyboardType = UIKeyboardTypeDefault;
    _textField.borderStyle = UITextBorderStyleRoundedRect;
    _textField.delegate = self;
    [self.view addSubview:_textField];
    
    //注册通知,用于接收通知,接收通知的名称必须和发送通知的名称保持一致才能接收到,否则无法接收到发出的通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notiReceived:) name:@"TransDataNoti" object:nil];
}

- (void)notiReceived:(NSNotification*)sender {
    self.textField.text = sender.userInfo[@"content"];
    self.label.text = sender.userInfo[@"content"];
}

- (void)dealloc {
    //移除所有通知
//    [[NSNotificationCenter defaultCenter] removeObserver:self];
    
    //移除某个通知
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"TransDataNoti" object:nil];
}

- (void)jump:(UIButton*)button {
    NewViewController *show = [[NewViewController alloc] init];
    show.modalPresentationStyle = UIModalPresentationFullScreen;
    [self presentViewController:show animated:YES completion:nil];
}

@end
  • 效果图

3232

  • 点击跳转按钮进入第二个界面并且在textField中输入内容

436

  • 再点击返回按钮返回第一个界面,发现label和textField中都有刚才输入的内容,传值成功

234

补充:

一.这是我豪哥发现的问题,让我学到了:

这是注册通知:
[[NSNotificationCenter defaultCenter] postNotificationName:@"Network" object:nil userInfo:self];
这是注册观察者:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ClickEvents:) name:@"Network" object:nil];

如果你注册观察者处的object写为nil,那么你注册通知的object写什么都可以接收到数据,但是你如果注册观察者处的object写为self,那么你注册通知的object只能写self,写其他的你都获取不到数据。
这是因为通知的查找方式并不是我们想象的那样,从注册通知处找观察者,恰恰相反的是,它是从你注册的观察者来找通知的,注册观察者的时候object写为nil它就代表可以接收所有的通知发来的数据。但是你要是写为self,它就会从注册中心来找self,找不到就不会调用,所以在这里我建议大家尽量把通知处的object都写为nil,防止不必要的麻烦,当然这只是对像我一样的菜鸟来说。

二.这是我美丽的房学姐问的:

假如你一个通知接收到通知然后执行回调方法为1秒,有10个观察者,那么得需要多长时间?

这个问题的答案是要需要10秒钟,因为通知的串联的关系,只能执行完一个后再执行另一个,这就相当于一个循环一样的,它会逐一执行,知道执行完毕,具体的让它共同执行的方法我还没太了解到,等了解了再添加补充。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
iOS中,可以通过WKWebView与JavaScript进行交互传值。以下是一些常见的方法: 1. 使用JavaScriptCore框架:在iOS 7及以上版本中,可以使用JavaScriptCore框架来实现WKWebView与JS的交互传值。具体实现步骤如下: (1)在iOS中创建一个JSContext实例,通过该实例可以操作JS环境。 (2)将JSContext实例设置到WKWebView的配置对象中。 (3)在JS中调用iOS方法时,可以通过window.webkit.messageHandlers对象进行调用,例如window.webkit.messageHandlers.methodName.postMessage(params)。 (4)在iOS中,可以通过WKScriptMessageHandler代理方法来接收JS传递的消息,并进行处理。 2. 使用WKScriptMessageHandler协议:在iOS 8及以上版本中,可以通过WKScriptMessageHandler协议来实现WKWebView与JS的交互传值。具体实现步骤如下: (1)在WKWebView的配置对象中设置WKUserContentController的代理对象,并添加需要监听的JS方法名。 (2)在JS中调用iOS方法时,可以通过window.webkit.messageHandlers对象进行调用,例如window.webkit.messageHandlers.methodName.postMessage(params)。 (3)在iOS中,可以通过WKScriptMessageHandler代理方法来接收JS传递的消息,并进行处理。 无论使用哪种方法,都需要注意JS和iOS之间传递的据类型和格式。通常,JS传递的是字符串类型的据,在iOS中需要进行解析和转换。同时,为了避免安全问题,需要对JS传递的据进行校验和过滤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值