在Swift中使用结构时,如何简洁地定义模型对象?

时间:2014-10-28 14:04:59

标签: xcode swift struct model

我在某处读到,使用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. 人们只是保持原样,并定义映射器,以便没有冗余?如果是这样的话 - 这是一个很好的例子吗?
  4. 感谢。

2 个答案:

答案 0 :(得分:3)

当面对这个时,我会为获取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)

答案 1 :(得分:0)

一些想法:

  • 在传递模型数据时,您是否可以共享建议使用结构而不是类的最佳实践?我原以为按值传递结构(特别是大结构)比通过引用传递类实例效率低。

    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 Patterns键值观察部分。

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