如何从ViewControllerB获取ViewControllerA的引用以修改其属性
解决从ViewControllerB修改ViewControllerA属性的问题
首先先修正你启动ViewControllerB代码里的语法错误:initWithRootViewController: 参数应该是实例 myVC,而不是类名 CustomVC,修正后的代码:
- (void) launchSecondVC { UIStoryboard *storyBoard = self.storyboard; CustomVC * myVC = [storyBoard instantiateViewControllerWithIdentifier:@"myvc"]; UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:myVC]; [self presentViewController:nav animated:YES completion:nil]; }
下面提供几种可靠的方法来实现你的需求:
方法一:直接传递ViewControllerA的引用(简单直接)
- 在
CustomVC(即ViewControllerB)的头文件中添加弱引用属性:
// CustomVC.h #import "FirstCustomVC.h" @interface CustomVC : UIViewController @property (nonatomic, weak) FirstCustomVC *sourceVC; @end
- 在启动ViewControllerB时,把当前ViewControllerA的实例赋值给这个属性:
- (void) launchSecondVC { UIStoryboard *storyBoard = self.storyboard; CustomVC * myVC = [storyBoard instantiateViewControllerWithIdentifier:@"myvc"]; // 传递引用 myVC.sourceVC = self; UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:myVC]; [self presentViewController:nav animated:YES completion:nil]; }
- 在ViewControllerB中完成操作后,直接通过引用修改属性并关闭:
// 关闭并启用ViewControllerA的按钮 self.sourceVC.myButton.enabled = YES; [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
方法二:使用代理模式(解耦更规范)
这种方式更符合iOS开发的设计规范,降低VC之间的耦合度:
- 在
CustomVC.h中定义代理协议:
// CustomVC.h @protocol CustomVCDelegate <NSObject> // 定义操作完成后的回调方法 - (void)customVCDidFinishOperation; @end @interface CustomVC : UIViewController @property (nonatomic, weak) id<CustomVCDelegate> delegate; @end
- 在
FirstCustomVC中遵守协议并实现回调方法:
// FirstCustomVC.h #import "CustomVC.h" @interface FirstCustomVC : UIViewController <CustomVCDelegate> // ... 你的其他属性,比如myButton @end // FirstCustomVC.m @implementation FirstCustomVC // ... 其他代码 - (void)customVCDidFinishOperation { self.myButton.enabled = YES; } - (void)launchSecondVC { UIStoryboard *storyBoard = self.storyboard; CustomVC * myVC = [storyBoard instantiateViewControllerWithIdentifier:@"myvc"]; myVC.delegate = self; UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:myVC]; [self presentViewController:nav animated:YES completion:nil]; } @end
- 在ViewControllerB中完成操作后,调用代理方法并关闭:
// CustomVC.m - (void)finishOperation { if ([self.delegate respondsToSelector:@selector(customVCDidFinishOperation)]) { [self.delegate customVCDidFinishOperation]; } [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; }
方法三:使用通知中心(适合跨多层VC的场景)
如果VC层级复杂,代理或直接引用不太方便,可以用通知实现:
- 在
FirstCustomVC中注册通知并实现响应方法:
// FirstCustomVC.m - (void)viewDidLoad { [super viewDidLoad]; // 注册通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(enableMyButton) name:@"CustomVCDidFinishOperation" object:nil]; } - (void)enableMyButton { self.myButton.enabled = YES; } - (void)dealloc { // 移除通知观察者,避免野指针 [[NSNotificationCenter defaultCenter] removeObserver:self]; }
- 在ViewControllerB中完成操作后发送通知并关闭:
// CustomVC.m - (void)finishOperation { // 发送通知 [[NSNotificationCenter defaultCenter] postNotificationName:@"CustomVCDidFinishOperation" object:nil]; [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; }
补充:修复你原代码中获取ViewControllerA的方式(不推荐,耦合度高)
如果你一定要通过层级获取,需要先拿到导航控制器的presentingViewController,再强制类型转换:
// 在CustomVC中 FirstCustomVC *vcA = (FirstCustomVC *)self.navigationController.presentingViewController; if ([vcA isKindOfClass:[FirstCustomVC class]]) { vcA.myButton.enabled = YES; } [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
这种方式不推荐,因为一旦VC层级变化,代码就会失效,维护性差。
内容的提问来源于stack exchange,提问作者user6631314
相关产品推荐
相关产品推荐

