1

我们正在构建一个使用Realm作为我们的模型/数据库的iOS应用程序,但我们希望设计客户端,以便它可以轻松地适应将来可能发生的REST-ful API中的更改。假设我们正在为适应不同活动的体育竞赛组织开发应用程序。根据正在玩什么运动,每个事件都有不同类型的事件类型。现在API只返回足球,棒球和足球,但将来它可能会扩展到包括篮球。之后它可能会消除棒球。我设计的领域对象,使事件从事件类型使用这样的一对多关系脱钩:如何根据REST-ful API中的更改为MVC for iOS应用动态创建模型?

class EventTypeGroup: Object { 
    dynamic var name = "" 
    let eventTypes = List<EventType>() 
} 

class EventType: Object { 
    dynamic var name = "" 
    dynamic var descriptionText = "" 
} 

的EventTypeGroup是描述事件类型(在这种情况下,其运动)的类会在比赛中出场。我使用这种设计是因为在Realm中不支持字典,我们可以用一组关联的属性来存储事件类型。

为了使模型适应未来API的变化,以便在添加或删除特定组织的运动时使用了如下的抽象工厂模式。这样,如果不使用符合现代Swift设计原则的枚举,就无法创建事件。我遇到的问题是,假设我们只在用户打开应用程序时检查API对事件类型(体育)的更改,如何在应用程序已打开的情况下更改模型?如果这些字段发生变化,数据库是否需要迁移?

protocol EventTypeGroupFactory { 

    func createEventTypeGroup(List<EventType>) -> EventTypeGroup 

} 

protocol EventTypeFactory { 

    func createEventTypes() -> List<EventType> 

} 

class SportEventGroupFactory: EventTypeGroupFactory { 
    func createEventTypeGroup(withEventTypes: List<EventType>) -> 
    EventTypeGroup { 
     //implement logic to create an EventTypeGroup for the SportEventGroup 

    } 
} 

class SportEventTypeFactory: EventTypeFactory { 
    EventTypeGroup { 
    func createEventType() -> EventType { 
     //implement logic to create an EventType for the SportEventType 
    } 
} 


class EventTypeGroup: Object { 

    let eventTypes = List<Int> 
    enum EventType { 
    } 
} 

class EventType: Object { 

    var type: Int? 
    name: String? 
    description: String? 
} 

class Event: Object { 

    static enum EventType 
    init(eventTypeWithRawValue:) { 

    } 
} 

另外,我怎么会是指在我现在写的代码的类的不同变化,如果我不知道他们会如何定义做。我猜测抽象工厂模式可能不是解决这个问题的最佳方法,但我不确定我应该考虑哪些其他选项或者如何解决基于API更改的模型中可轻松扩展类型的问题。

回答

2

我觉得你太过于复杂了。只需将名为“eventType”的字符串属性添加到您的Event模型。

例如,通常情况下,如果你没有需要保持动态的东西,你可能会做这样的事情:

enum EventType { 
    case soccer 
    case baseball 
    case football 
} 

// Your Event model 
struct Event { 
    var date: Date 
    var eventType: EventType // a static type :) 
} 

但在你的情况,相反,你可以做这样的事情:

// Your Event model without any enums 
struct Event { 
    var date: Date 
    var eventType: String // a dynamic type :(
} 

属性eventType然后可以是“足球”或“棒球”或“足球”。 (但编译器现在无法帮助你发现错误。)至于你的持久存储,只需要一个类型为eventType的字段并存储字符串。

动态类型让我很难过,因为Swift是多么好的静态,但它能让你得到你想要的。只要确保考虑边缘案例。为了不结束未定义的行为,例如,如果最终发现REST API不再支持的磁盘上的事件类型,则可以提前考虑应用程序应该执行的操作。例如,假设您有一个/eventTypes端点,以便您的应用的用户可以添加事件并对其进行相应的分类,并且它已返回“足球”,“棒球”和“足球”,并且您的用户已添加这些类型事件,你一直在磁盘上存储(Realm或CoreData或其他)。但是总有一天,后台有人(或通过后端)将“足球”改名为“美式足球”,我们希望没有人将“足球”改名为“足球”。 (所以现在你不能分辨一个事物是否被重命名或删除,而另一个添加。)然后,你接下来的事件类型的联合,你的终端返回和你在磁盘上找到什么?您是否允许用户添加仍旧存在于磁盘上但不再受REST API支持的旧事件类型,或仅显示它们?

对于活跃的用户,如果您的后端人员重命名事件类型或删除事件类型(而不是简单地添加它们),您可能会遇到这类边缘情况。只需与你的利益相关者讨论行为应该是什么。

+0

没有骰子上的EventType类我添加到您的回应?此外,您选择使用结构而不是类来实现Event模型的任何特定原因? – stonybrooklyn

+1

Re。结构:结构更安全(在Swift中,它们是按值传递的,而不是通过引用),并且在运行时也更快(无法维护)。但是如果你需要子类和协议不够,那么回到使用类。 – willtherussian

+1

Re。 EventType类:是的,如果需要包装其他数据并将字符串(将采用诸如“棒球”和“足球”之类的值的字符串)放入其中,那么可以使用类或结构作为eventType属性。重点是你仍然在使用字符串而不是枚举。 – willtherussian