【问题标题】:How can I concisely define model objects when using structs in Swift?在 Swift 中使用结构时如何简洁地定义模型对象?
【发布时间】:2014-12-23 23:27:34
【问题描述】:

我在某处读到,使用 Swift 传递模型数据时使用结构是最佳实践。

我一直在这样做,但我一直想知道在创建像这样的大型(和不断增长的)用户数据对象方面我能做些什么:

struct UserAccount {

    var id: String?
    let authId: String

    let emailAddress: String
    let mobilePhoneNumber: String

    let firstName: String
    let lastName: String

    let countryCode: String
    let homepageUrl: String
    let tagline: String

    let pictureUrl: String

    let accountState: AccountState = .NoAccount

    // ... 
}

这或多或少是我在创建用户帐户时使用的,但后来不得不在代码中实例化巨大的对象感觉既麻烦又错误。我正在使用 json-swift 解析 JSON 响应,但随后必须单独实例化模型,如下所示:

let id = jsonData["id"].string!
let authId = jsonData["authId"].string!
let emailAddress = jsonData["emailAddress"].string!
let mobilePhoneNumber = jsonData["mobilePhoneNumber"].string!
let firstName = jsonData["firstName"].string!
let lastName = jsonData["lastName"].string!
let countryCode = jsonData["countryCode"].string!
let homepageUrl = jsonData["homepageUrl"].string!
let tagline = jsonData["tagline"].string!
let pictureUrl = jsonData["pictureUrl"].string!
let accountState = convertAccountStateStringToEnum(jsonData["accountState"].string!)


let userAccount = UserAccount(
    id: id,
    authId: authId,
    emailAddress: emailAddress,
    mobilePhoneNumber: mobilePhoneNumber,
    firstName: firstName,
    lastName: lastName,
    countryCode: countryCode,
    homePageUrl: homepageUrl,
    tagline: tagline,
    pictureUrl: pictureUrl,
    accountState: accountState
)

上面我在实例化结构之前已经实例化了变量可能看起来很荒谬,但我这样做的原因是当 IDE 从结构内给我类型强制错误时,很难理解出了什么问题,因此这使我在更改模型时可以更快地进行故障排除。对此有什么想法吗?

我的问题:

稍后,该用户对象可能会在服务器端包含更多数据,并且实例化 50 多行的使用模型似乎是个坏主意,因此:

  1. 是否有以更简单的方式创建结构的解决方案?模式有名称吗?
  2. 我应该创建与特定任务相关的用户模型吗?例如,用于 GET 或 PUT 配置文件的 UserAccount 模型可能与用于身份验证、获取用户设置或列出我的服务上最受欢迎的帐户的模型不同。
  3. 人们是否只是保持原样并定义映射器以便没有冗余?如果是这样 - 有什么好的例子?

谢谢。

【问题讨论】:

    标签: xcode swift struct model


    【解决方案1】:

    一些想法:

    • 您能否分享在传递模型数据时建议使用结构而不是类的最佳实践的参考?我会认为通过值传递结构(尤其是大结构)会比通过引用传递类实例效率低。

      请参阅The Swift Programming Language: Classes and Structures 中的在类和结构之间选择,这表明您希望在以下情况下使用结构:

      • 结构的主要目的是封装一些相对简单的数据值。

      • 当您分配或传递该结构的实例时,预期封装的值将被复制而不是引用是合理的。

      • 结构存储的任何属性本身都是值类型,也应该被复制而不是引用。

      • 结构不需要从另一个现有类型继承属性或行为。

      您的用户对象似乎不符合此条件。我会认为课堂方法更合乎逻辑。

    • 顺便说一句,如果使用类,如果类符合 KVO,您还可以简化代码以实例化对象。例如,您可以遍历键名数组,从 JSON 中获取与每个键名关联的值,然后使用 setValue:forKey: 为该特定键设置对象的属性。

      有关 KVO 合规性的更多信息,请参阅Key-Value Observing Programming Guide: KVO Compliance。有关如何使 Swift 对象符合 KVO 的更多信息,请参阅Using Swift with Cocoa and Objective-C: Adopting Cocoa Design PatternsKey-Value Observing 部分。

    • 就不同任务的单独用户模型而言,这对我来说没有意义。您可能有不同的对象用于不同的功能目的(例如帐户/身份验证对象),这些对象可能会引用用户对象,但拥有不同类型的用户类/结构似乎没有意义。

    【讨论】:

      【解决方案2】:

      当遇到这种情况时,我会为获取 JSON 数据的模型构建另一个初始化程序:

      struct UserAccount {
          // ...
          init(jsValue: JSValue) {
              id = jsonData["id"].string!
              authId = jsonData["authId"].string!
              emailAddress = jsonData["emailAddress"].string!
              mobilePhoneNumber = jsonData["mobilePhoneNumber"].string!
              firstName = jsonData["firstName"].string!
              lastName = jsonData["lastName"].string!
              countryCode = jsonData["countryCode"].string!
              homepageUrl = jsonData["homepageUrl"].string!
              tagline = jsonData["tagline"].string!
              pictureUrl = jsonData["pictureUrl"].string!
              accountState = convertAccountStateStringToEnum(jsonData["accountState"].string!)
          }
      }
      

      然后您可以简单地从您的 JSON 数据创建新的 UserAccount 实例:

      let userAccount = UserAccount(jsValue: jsonData)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多