我如何根据 REST-ful API 的变化在 MVC 中为 iOS 应用创建动态模型?

How do I make model in MVC for iOS app dynamic based on changes in REST-ful API?

我们正在构建一个 iOS 应用程序,使用 Realm 作为我们的模型/数据库,但我们想要设计客户端,以便它可以轻松适应 REST-ful API 中可能发生的变化未来。假设我们正在为体育比赛组织开发一个应用程序,以适应不同的事件。根据正在进行的运动项目,每个事件都有不同类型的事件类型。目前 API 只有 returns 足球、棒球和橄榄球,但将来它可能会扩展到包括篮球。后来它可能会淘汰棒球。我设计了 Realm 对象,以便使用如下一对多关系将事件与事件类型分离:

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

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

EventTypeGroup 是 class 描述将在活动中进行的活动类型(在本例中为哪些运动)。我使用这种设计是因为 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:) {

    }
}

此外,如果我不知道如何定义它们,我将如何在我现在编写的代码中引用 classes 的不同变体。我猜抽象工厂模式可能不是解决这个问题的最佳方式,但我不确定我应该考虑哪些其他选项或如何解决使类型在基于 API 更改的模型中易于扩展的问题.

我认为你把它复杂化了。只需将名为 "eventType" 的字符串 属性 添加到您的事件模型中即可。

例如,通常情况下,如果您不需要保持动态,您可能会这样做:

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 可以是 "soccer" 或 "baseball" 或 "football"。 (但编译器现在无法帮助您捕获错误。)至于您的持久存储,只需在那里有一个 eventType 类型的字段并存储字符串。

动态类型让我很伤心,因为静态 Swift 非常好,但它可以满足您的需求。只要确保考虑边缘情况即可。为了不以未定义的行为结束,请提前考虑您的应用程序应该做什么,例如,如果您最终在磁盘上使用 REST 不再支持的事件类型 API.

例如,假设您有一个 /eventTypes 端点,以便您应用的用户可以添加事件并相应地对其进行分类,并且它一直在返回 "soccer"、"baseball" 和 "football" 并且您的用户一直在添加这些类型的事件,并且您一直在将它们存储在磁盘上(在 Realm 或 CoreData 或其他地方)。但是有一天后端(或通过后端)有人将 "football" 重命名为 "american football",希望没有人也将 "soccer" 重命名为 "football"。 (所以现在你无法判断一个东西是否被重命名或删除并添加了另一个。)然后你是否将你的 /eventTypes 端点 returns 的事件类型与你在磁盘上找到的东西结合起来?您是否让用户添加仍然存在于磁盘上但不再受您的 REST API 支持或仅显示它们的旧事件类型?

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