如何通过Notification Observer在A、B类间实现推送导航?
嘿,我来分享几个实际开发中能让这个通知实现更健壮、更易维护的建议:
务必移除通知观察者,防止崩溃
目前你的代码只添加了观察者,但没有在A类销毁时移除。如果A类的ViewController已经被释放(比如被pop出导航栈),这时候B类发送通知,系统会尝试给已释放的对象发送消息,直接导致崩溃。建议在dealloc方法里移除观察者:- (void)dealloc { // 移除当前对象的所有观察者,也可以精准移除指定通知 [[NSNotificationCenter defaultCenter] removeObserver:self]; }要是你想更精准,也可以只移除这个特定的通知:
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"notificationName" object:nil];用常量替代硬编码的通知名称
直接写@"notificationName"属于硬编码,不仅容易打错,后续重构或者修改通知名称时要找遍所有用到的地方,非常麻烦。建议定义全局常量:// 在公共头文件或者.pch文件中声明 extern NSString *const kNotificationSomethingHappens; // 在A类或者专门的常量文件中实现 NSString *const kNotificationSomethingHappens = @"notificationName";之后注册和发送通知都用这个常量,代码可读性和可维护性都会提升不少。
预留数据传递的扩展空间
当前的通知没有传递任何数据,如果以后需要从B类给A类传参数(比如跳转页面需要的配置信息),可以利用通知的userInfo字典:
// B类发送通知时携带数据NSDictionary *userInfo = @{@"targetVCParam": @"someValue"}; [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationSomethingHappens object:self userInfo:userInfo];// A类接收时取出数据
-(void)somethingHappens:(NSNotification*)notification { NSString *param = notification.userInfo[@"targetVCParam"]; // 用参数做相应处理 // ... 原有跳转代码 }这样后续扩展功能不用修改通知的基础结构,更灵活。
缩小通知接收范围(可选)
你注册观察者时用了object:nil,这意味着A类会接收所有发送notificationName的通知。如果B类是这个通知的唯一发送者,建议在注册时指定B类的实例,这样只接收来自B类的通知,避免其他地方误发相同名称的通知导致A类意外触发:// 假设你能在A类中拿到B类的实例bInstance [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(somethingHappens:) name:kNotificationSomethingHappens object:bInstance];完善页面跳转的代码
目前你在somethingHappens:里创建了导航控制器和目标VC,但没有把这个导航控制器显示出来!记得加上present或者push的逻辑,比如:-(void)somethingHappens:(NSNotification*)notification { NavigationController *navigationController = [self.storyboard instantiateViewControllerWithIdentifier:@"contentViewController"]; UIViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"loyaltyVC"]; navigationController.viewControllers = @[vc]; // 显示导航控制器,这里根据你的需求选present或者push [self presentViewController:navigationController animated:YES completion:nil]; }另外,建议加上实例化失败的判断,避免storyboard ID写错导致崩溃:
NavigationController *navigationController = [self.storyboard instantiateViewControllerWithIdentifier:@"contentViewController"]; if (!navigationController) { NSLog(@"Failed to load NavigationController with ID: contentViewController"); return; }
内容的提问来源于stack exchange,提问作者serkanmalagic

