最近在开发iOS应用程序时,我遇到了一个问题,我需要有两个视图控制器来共享一些数据,甚至从另一个视图控制器检索UI状态。
为了履行这一功能,我为视图控制器定义并实现了委托。
@protocol ViewControllerADelegate <NSObject>
-(id)dataForSomePurposeForViewController:(ViewController *)viewController
@end
然后在推送一个新的viewController(在ViewControllerA中)时,如果需要,我会将currentViewController设置为新控制器的委托。
viewControllerA.delegate = currentViewController
[currentViewController.navigationController pushViewController:viewControllerA animated:YES]
之后我可以调用委托选择器并从上一个视图控制器获取数据,如:
//in viewControllerA
self.someData = [self.delegate dataForSomePurposeForViewController:self]
上面的代码只是一个显示我尝试过的例子,代码中可能存在一些错误,并且不会过多关注它。
事实上,上述方法运行良好,到目前为止从未引起任何问题。但当我与我的一位同事(一位Android开发人员)讨论过此事时,我被告知我在iOS中所做的事情在Android中无效。在Android的任务堆栈模型中,视图控制器(在Android中称为Activity)不会执行任何代码或响应任何函数调用,当它不在导航堆栈的顶部时。
这让我担心以这种方式使用委托。我google了很多,现在我知道我的实现与MVC设计模式有点对比,视图控制器之间通信的最佳方式可能是设置共享模型。
但是,更改当前代码是一项耗时的任务。所以我的问题是:
任何帮助或思考都会受到赞赏和感谢。
答案 0 :(得分:1)
在不知道dataForSomePurposeForViewController
返回的数据类型及其生成方式的情况下,作为您所描述的控制器关系的一般设计选择,我会选择Dependency Injection 类型的数据传递新控制器所需数据的实现。使用委托进行控制,例如将新控制器从堆栈中弹出,并保存新控制器对传递给它的模型所做的更改。
某些Apple examples核心数据应用程序涉及创建一个临时管理对象上下文(MOC),并将其传递到“添加新记录”中。包含要由新控制器操纵的数据的控制器。该MOC由控制器创建和拥有,该控制器启动&#39;添加&#39;控制器,并且还负责将其删除并在添加&#39;之后保存更改。控制器弹出。添加控制器的委托是启动它的控制器。
答案 1 :(得分:1)
1)如果您对堆栈的顶级控制器持有强引用,则可能无法解除分配。将委托属性定义为弱。委托模式不仅是控制器之间通信的一种方式。您也可以使用块或通知中心。它的风格问题.2)它取决于应用程序架构,有时它更好地拥有共享模型,但在大多数情况下,委托有利于沟通。下面的例子。 创建具有复制属性 (why copy)
的块类型的属性"
然后在firstViewController控制器中执行下一步操作:
typedef void(^ApproveAction)(NSString *name);//return type(^name)(arguments)
@interface SecondViewController : UIViewController
@property (nonatomic, copy) ApproveAction onApproveTap;
+ (NSString *)storyboardID;
@end
使用块读取 this
来防止保留周期然后再在SecondViewController调用块中(例如在某个按钮上):
#pragma mark - Actions
- (IBAction)presentAction:(id)sender
{
SecondViewController *secondVC = [self.storyboard instantiateViewControllerWithIdentifier:[SecondViewController storyboardID]];
secondVC.onApproveTap = ^(NSString *name)
{
NSLog(@"%@",name);
};
[self presentViewController:secondVC animated:YES completion:nil];
}
希望这有帮助。