将NSArray模型对象传递给视图对象的最佳(设计)方法是什么?

时间:2010-08-27 14:51:26

标签: iphone objective-c cocoa-touch model-view-controller oop

我有一个BankAccount模型类,其中包含帐号,银行名称,事务等数据。事务是Transaction类的每个实例,并包含在事务NSArray中。

我还有一个BankAccountView,可以在一个视图中显示所有这些内容。现在我将所有数据作为单独的变量传递(即bankAccountView.accountNumber = bankAccount.accountNumber,bankAccountView.bankName = bankAccount.bankName)。

当我需要将事务传递给视图时,会出现问题/困境。我学会了保持模型和视图类分离,所以我认为将BankAccount的事务数组传递给BankAccountView并不是一件好事,因为该数组包含Transaction模型类的实例。

所以我现在正在做的是:我将每个Transaction实例转换为NSDictionary,然后将bankAccountView.transactions设置为包含这些词典的NSArray。它可以工作,我觉得它保持我的模型和视图类是分开的,但它也感觉过于复杂,就像我正在为可能更简单的某些东西编写大量代码。

有更好的方法吗?提前谢谢。

2 个答案:

答案 0 :(得分:3)

我认为你已经走得太远了,应该直接传递整个BankAccount对象。没有转换,没有环境,只是将它传递给视图。你做的那种分离(对我而言)感觉有点像在苍蝇上用大炮射击......

我的论点:

  • 您的视图只能显示BankAccounts,为什么不传递它正在显示的对象?
  • 这使您的界面非常清晰,只需要一个属性:@property(...) BankAccount *bankAccount;
  • 传递对象的
  • (EDIT)封装了所有属性之间的依赖关系。他们不是独立的,他们组成银行账户。这应该是可见的。
  • 不需要转换,如果扩展模型
  • ,则无需更改界面
  • 只有当您的视图独立于其显示的数据时,才需要模型和视图之间非常强大的划分。匿名化视图只能显示一种非常特定类型的数据:银行帐户。
  • 只有在撰写了几个可重用组件的视图时,所有转换才有意义。你似乎不是这样,这只是不必要的工作。
  • MVC仍然保留:模型不知道控制器或视图,视图不直接知道控制器,控制器将数据从视图传递到模型并对操作作出反应。

如果您不想直接传递该类,请设计一个协议,该协议将视图所需的所有属性封装在银行帐户对象中,并让类BankAccount实现它。 但是,这只有在您(计划)将不同类的类作为数据传递给视图时才有意义。如此不同,这些类不共享具有所有这些属性的公共超类。如果只有这个简单的类或继承的类,请使用最简单的解决方案:直接传递帐户。

为了能够在重做时触发重绘,我建议您使用Key-Value-Observation。这是一种非常干净的方式来保持匿名并且只需编写很少的代码。在视图中的init方法中,针对您要观察的每个属性执行以下操作:

[self addObserver:self forKeyPath:@"bankAccount.<property>" withOptions:0 context:@"redraw"];

然后您实施observeValueForKeyPath...

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (context == @"redraw") {
        [self setNeedsDisplay];
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

我发现这是一个非常干净的方法,开销很小,我在我自己的项目中大量使用。

答案 1 :(得分:1)

我看待MVC范式的方式(并且记住,它只是一个范例 - 它可以解释)是模型对视图一无所知,视图对模型一无所知。他们不应该直接互动;严格来说,你的观点不应该有你的模型实例。

这是控制器变得重要的地方。我打算假装你的BankAccountView有一些标签来显示帐户信息,也可能是一个用于显示所有帐户交易的桌面视图(让我们假装,只是为了说明)。那么你会有这样的事情:

MyBankAccountViewControllerUIViewController子类(MVC中的 C ),其视图是BankAccountView的实例。您的视图控制器还有一个BankAccount的实例。在适当的时间(例如-viewDidLoad),您需要使用BankAccount模型中的信息(self.bankAccountView.accountNameLabel.text = self.myBankAccount.name或其他内容)填充您的视图(及其子视图)。

MyBankAccountViewController还可以作为视图中tableview的委托和数据源,为其提供列出帐户交易信息的单元格。

当您的视图中发生需要更改模型的内容时(例如,用户按下“关闭此帐户”按钮),“事件”将从视图发送到控制器(通过委派,目标)动作,或您选择的其他一些机制)。然后控制器决定做什么,例如[self.bankAccount closeBankAccount];

就像我说的,这就是我如何解释MVC(我严格而且迂腐地看待它),它可能使代码复杂化,而不仅仅是直接传递模型。如果你只是在一个地方使用这个视图,并且从不计划重复使用它,那么直接传入可能会更简单。请记住,这会导致将来更难以重复使用(这是MVC的关键卖点之一:您的模型和您的视图应该是可重用的;您的控制器不会重复使用。)< / p>