iOS Objective-C:VC/类初始化方法及NSNotificationCenter传参问题咨询
Objective-C开发问题解答:VC初始化与通知中心适配
嘿,我来帮你解决这两个iOS Objective-C开发里的常见问题😉
一、如何在Objective-C环境下初始化视图控制器(VC)或类?
1. 普通类的初始化方式
- 无参基础初始化:对于不需要初始参数的类,直接用最经典的
alloc + init组合:YourCustomClass *instance = [[YourCustomClass alloc] init]; - 自定义带参初始化:如果类需要在创建时就传入配置信息,可以自定义初始化方法,比如:
// 在YourCustomClass.h中声明 - (instancetype)initWithTitle:(NSString *)title content:(NSString *)content; // 在YourCustomClass.m中实现 - (instancetype)initWithTitle:(NSString *)title content:(NSString *)content { self = [super init]; if (self) { self.title = title; self.content = content; } return self; } // 调用初始化 YourCustomClass *instance = [[YourCustomClass alloc] initWithTitle:@"测试标题" content:@"测试内容"];
2. 视图控制器(VC)的初始化方式
VC的初始化分纯代码、XIB、Storyboard三种场景:
- 纯代码VC初始化:直接调用
init即可,若需要指定自定义初始化逻辑,重写init方法:FirstVC *firstVC = [[FirstVC alloc] init]; - XIB关联的VC初始化:如果VC是用XIB文件创建的,用
initWithNibName:bundle:指定XIB名称:SecondVC *secondVC = [[SecondVC alloc] initWithNibName:@"SecondVC" bundle:nil]; - Storyboard中的VC初始化:先获取对应Storyboard实例,再通过
Storyboard ID实例化VC(注意要在Storyboard里给VC设置好Storyboard ID):UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; SecondVC *secondVC = [mainStoryboard instantiateViewControllerWithIdentifier:@"SecondVCID"];
二、NSNotificationCenter通知无法传递的问题解决
首先拆解你的问题:首次启动时SecondVC还没被初始化,自然没注册通知监听,所以收不到FirstVC发的通知。至于要不要在- (BOOL)application:didFinishLaunchingWithOptions:里初始化SecondVC?我非常不推荐这么做,因为这会提前把SecondVC加载进内存,平白增加启动时的内存开销,拖慢App启动速度,除非你的业务场景真的需要它在后台静默存在(这种情况极少)。
下面给你几个更合理的解决方案:
方案1:缓存数据 + 延迟处理
当FirstVC点击按钮时,先判断SecondVC是否已经存在于视图层级中:
- 如果存在:直接发送通知;
- 如果不存在:先缓存数据,等SecondVC初始化完成后,主动读取缓存数据处理。
示例代码:
// FirstVC中按钮点击事件 - (IBAction)triggerSecondVCAction:(UIButton *)sender { NSDictionary *transferData = @{@"userId": @"123", @"userName": @"Hanz"}; // 检查SecondVC是否在导航栈中 BOOL isSecondVCExist = NO; for (UIViewController *vc in self.navigationController.viewControllers) { if ([vc isKindOfClass:[SecondVC class]]) { isSecondVCExist = YES; break; } } if (isSecondVCExist) { // 直接发送通知 [[NSNotificationCenter defaultCenter] postNotificationName:@"UserInfoUpdate" object:nil userInfo:transferData]; } else { // 缓存数据到AppDelegate(也可以用单例类管理,更优雅) AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate; appDelegate.cachedUserInfo = transferData; // 直接跳转到SecondVC SecondVC *secondVC = [[SecondVC alloc] init]; [self.navigationController pushViewController:secondVC animated:YES]; } } // SecondVC的viewDidLoad方法 - (void)viewDidLoad { [super viewDidLoad]; // 注册通知监听 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleUserInfoUpdate:) name:@"UserInfoUpdate" object:nil]; // 检查缓存数据并处理 AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate; if (appDelegate.cachedUserInfo) { [self handleUserInfoUpdate:nil]; // 处理完清空缓存 appDelegate.cachedUserInfo = nil; } } // 通知处理方法 - (void)handleUserInfoUpdate:(NSNotification *)notification { NSDictionary *userInfo = notification.userInfo ?: ((AppDelegate *)[UIApplication sharedApplication].delegate).cachedUserInfo; // 这里写你的数据处理逻辑,比如更新UI NSLog(@"收到数据:%@", userInfo); } // 记得在dealloc中移除监听,避免野指针 - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; }
方案2:直接给VC传参(更简洁)
如果你的需求是点击按钮后跳转到SecondVC并传递数据,完全可以不用通知中心,直接给SecondVC的属性赋值:
// FirstVC按钮点击事件 - (IBAction)goToSecondVCAction:(UIButton *)sender { NSDictionary *transferData = @{@"userId": @"123", @"userName": @"Hanz"}; SecondVC *secondVC = [[SecondVC alloc] init]; // 直接给VC的属性赋值 secondVC.passedUserInfo = transferData; [self.navigationController pushViewController:secondVC animated:YES]; } // SecondVC.h中声明属性 @property (nonatomic, strong) NSDictionary *passedUserInfo; // SecondVC的viewDidLoad中处理数据 - (void)viewDidLoad { [super viewDidLoad]; if (self.passedUserInfo) { NSLog(@"直接收到数据:%@", self.passedUserInfo); // 处理数据逻辑 } }
这种方式比通知中心更直接,耦合性也更低,适合页面跳转时的数据传递场景。
方案3:单例类统一管理数据
如果你的数据需要在多个VC之间共享,可以创建一个单例的DataManager类,用来存储和获取数据:
// DataManager.h @interface DataManager : NSObject @property (nonatomic, strong) NSDictionary *sharedUserInfo; + (instancetype)sharedManager; @end // DataManager.m @implementation DataManager + (instancetype)sharedManager { static DataManager *manager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ manager = [[DataManager alloc] init]; }); return manager; } @end // FirstVC中存储数据 - (IBAction)sendDataAction:(UIButton *)sender { [[DataManager sharedManager] setSharedUserInfo:@{@"userId": @"123"}]; // 跳转到SecondVC SecondVC *secondVC = [[SecondVC alloc] init]; [self.navigationController pushViewController:secondVC animated:YES]; } // SecondVC中读取数据 - (void)viewDidLoad { [super viewDidLoad]; NSDictionary *userInfo = [[DataManager sharedManager] sharedUserInfo]; if (userInfo) { // 处理数据 } }
内容的提问来源于stack exchange,提问作者Hanz Cheah
相关产品推荐
相关产品推荐

