我对扩展方法的糟糕体验是my March 2016 talk at iOSoHo in New York的第一个也是最重要的部分的基础。我所说的关于扩展的大部分内容并不在幻灯片中。扩展方法有以下几个问题:
- 您只能有一个模型到视图的映射(没有另一个中间层来提供逻辑协调扩展属性)。这极大地损害了视图的可重用性。
- 关于第1点,即使你身边这个坐标,你可能会得到碰撞,如果你使用的型号很多地方,例如
name
再后来加入firstNameOnly
等绝对是一个模型只能不断遵循协议的一种方式,如果你想要这样做。
- 提供了替代模型的虚拟值,做汽车设计,调试,故障情况等,几乎是不可能的。您可能会发现自己正在为此编写一个结构 - 这是一个ViewModel。
- 如果您有一个视图需要多个模型来填充模型,或需要模型外部的信息,则视图模型会简化它们之间的协调。
通过ViewModel,这些重要情况变得微不足道。 (在演讲中,我所说的“命令”,因为他们完全匹配的四种设计模式定义命令刚; 设计模式笔记也被称为行动,即UIAlertAction)
我采取的做法是一个“ ViewModel“应该是轻量级的,不可变的,并且通过单向数据流分布。他们已经存储了属性,但是这只是为了移动数据,虚拟机本身是不可变的,一次性的。这与2017年3月iOSoHo上的Facebook提到的方法类似,但我认为他们不称他们为视图模型,只是轻量级对象。你可以在那里放置更复杂的逻辑,但最好是最多可以调用其他地方处理的更复杂的逻辑。
另外一个我认为是关键的问题,我的规则是,无论您称之为“ViewModel”,都不应该有程序员无法编写线框的属性。因此,一个var dateString : String
不var date : NSDate
。这是我在幻灯片中的厚脸皮术语,即“Modal Object Attribute Transformer”。但是有一点很重要:城堡需要能够吊起吊桥并在围困时进行;当网络中断(或还不存在)时,视图需要完全正常运行。如果您的观点能够做到这一点,您将在许多场景中拥有更容易的时间。
就在几个星期前,我采用了这种方法,并且能够在大约4天内创建多个复杂的屏幕,仅从设计开始工作,最终将由来自网络的数据填充,但目前没有任何模型或网络层。当数据层准备就绪后,我可以简单地编写一些创建方法init(with: Model)
或更好static func withModelforCase1(_ model: Model) -> ViewModel
并在创建方法中写入映射,然后在连接模型时,用这些创建方法替换static func debugCase1() -> ViewModel
。随着模型的发展,编译器会在这里抛出错误,只会在这里抛出错误;随着视图的发展,调整ViewModel,再次,编译器会在这里抛出错误,而且只会在这里抛出错误。没有其他代码需要被触及。
扩展在开始时看起来非常优雅,但实际上在模型和视图之间创建了紧密耦合。某种ViewModel方法是一个强大的系统,可满足现代iOS应用程序的需求 - 以及现代iOS应用程序开发。
大多数情况下,我的@import UIKit几乎总是处于“ViewModel”扩展模式。 – Mugunth
http://www.sprynthesis.com/2014/12/06/reactivecocoa-mvvm-introduction/ –
究竟为什么要这么做?我注意到NSManagedObject的子类是以相同的方式生成的,它是空的,但扩展中的属性。 ViewModel应该是objc中的结构体或NSObject。 –