我正在尝试开发一个小应用程序,你可以在其中使用SwifUI创建带问题的测试,但是对于像我这样的新手来说,找到如何让一切都顺利进行是越来越困难的。这个应用程序会在一个主滚动视图中显示一个问题列表,这些问题可以是不同的类型,如对或错、文本、多项选择等......并且可以是活动的或不活动的。
我认为所有不同类型的问题采用相同的协议会很棒。这个协议还将定义一个函数或计算属性,尝试修改与该视图交互的任何参数时出现问题。让'比如说我想添加一个切换按钮来激活或React问题,修改问题的一个值。使用我实现的不同解决方案,我没有得到正在重建/更新的视图。
我尝试了几种方法来实现这一点,比如用@State或@Binding Package 那些应该更新其值的属性。我还尝试将这些属性转换为ObservableObject,添加采用ObservableObject协议的新类,但是没有效果。唯一看起来有效的方法是,对于任何类型的Question,创建一个视图,带有一个可观察的ViewModel。稍后,在显示所有问题的视图中,我必须创建一个包含所有不同可能性的Switch。
我不喜欢这个解决方案的地方是,如果我想添加一个新类型的问题,我必须修改这个主视图,为这个新类型的问题包括一个额外的情况,这违反了开放-封闭原则。
你有什么建议的家伙分配这个责任给任何问题类,而不是主视图?
提前感谢您:)
1条答案
按热度按时间yuvru6vn1#
通常你不想让模型知道视图,这是逆向的,但是我们经常想把具体的选择逻辑隐藏在一个单独的调用后面,这个调用根据提供的数据做不同的事情(类似于通过函数重载的多态性)。
其关键思想是将Factory Pattern与Visitor Pattern结合使用,以保持开闭原理的和谐。
当我们对常规对象执行此类操作时,我们通常使用工厂方法来返回输入数据的正确子类。Inside that factory method usually sits a
switch
statement.工厂接口允许我们荣誉开-闭原则,这样当我们添加新的问题类型时,ContentView
不会发生变化。很可能,接下来的内容与您使用视图模型方法所得到的内容非常相似。在SwiftUI中,工厂风格视图的最佳方法是创建一个
QuestionView
,它知道如何为每个问题对象创建正确的具体视图。我希望default
+fatalError()
能让您考虑一下enum
在这里是如何有用的。在主视图中,它将是多态的,动态地响应实际的
Question
示例。提取答案的一个合理的方法是使用访问者模式,其结构类似于
Encodable
的encode(to encoder: Encoder)
。我们希望每个专业视图与其特定的Question
对象进行通信,然后希望Question
对象包含func record(answers: Answers)
的实现。到时候,遍历questions
并告诉他们记录他们的答案。(注意,我们可以添加各种Answers
实现,而不更改Question
子类,这与开-闭原则保持一致)。Question
对象类似于视图模型,它们是ObservableObjects
。要使其正常工作,它们不能是具有关联类型的协议,这会导致在数组中使用它们。
然后,每个问题子类型视图将监视其自己的
Question
示例:您只需将您的list of questions添加到预览中,然后查看它的工作方式:
除了玩具项目之外,我不确定我是否喜欢这个实现--我更喜欢更强的层分离。然而,这确实设置了一个多态视图,可以根据数据实现类型进行调整。关键思想是结合使用Factory Pattern和Visitor Pattern。