如果我使用委托进行视图控制器之间的通信,我会冒什么风险?

时间:2016-07-14 02:00:39

标签: ios objective-c delegates

最近在开发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设计模式有点对比,视图控制器之间通信的最佳方式可能是设置共享模型。

但是,更改当前代码是一项耗时的任务。所以我的问题是:

  1. 使用委托进行视图控制器通信有什么风险?
  2. 据我所知,拥有共享模型是最佳做法吗?如果是,我应该将此模型分配给谁?通过使用singleton?
  3. 任何帮助或思考都会受到赞赏和感谢。

2 个答案:

答案 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];
}

希望这有帮助。