用var初始化Codable结果

时间:2018-04-16 07:32:04

标签: swift4 codable

我需要在API调用之外定义的 var 对象中初始化JSONDecoder的结果。

apiService.GETAPI(url: apiStr, completion: {(success, result) in
            if(success) {
                let apiResponse = result.value as! NSDictionary
                let data = apiResponse.value(forKey: "data") as! NSDictionary
                    do {
                        let profileData = try JSONSerialization.data(withJSONObject: data.value(forKey: "profile"), options: .prettyPrinted)
                        print(profileData)
                        let profile = try JSONDecoder().decode(Profile.self, from: profileData)

                        print(profile.name)
                    }
                    catch {
                        print("json error: \(error.localizedDescription)")
                    }
            }
            completion(success)
        })

但我无法这样做。这是我的Profile Codable结构

struct Profile : Codable {
    var id : Int
    var name : String
    var member_id : Int
    var category_id : Int
    var membership_id : Int
    var information : String
    var city : String
    var love_count : Int
    var vendor_price : String
    var locality_name : String
    var phone : [String]
    var address : [Address]?
    var status : Int?
    var managed_by_wmg : Int?
}

怎么做。我需要它是var,因为我需要执行操作并稍后在其他代码中访问它。

2 个答案:

答案 0 :(得分:0)

正如我们已经在您的问题的评论中讨论的那样,您需要在闭包之外声明Profile类型的变量。

现在问题变成了"How to change Profile struct, so I can declare variable of it?"

为此你有几个选择。我将列出它们并评论选择哪个以及为什么。

选项1 将默认值添加到Profile struct的所有变量中,如下所示:var id : Int = 0,以便稍后可以使用var profile: Profile?声明它。使用此解决方案,您需要以对业务逻辑有意义的方式了解您期望的对象及其默认值。对于字符串或""整数,此类默认值的示例为0。这可能看起来不错,但它们是更好的解决方案。

选项2 Profile的所有变量设为可选,如下所示:var id : Int?。这听起来可能很奇怪,但却是处理服务器数据的最佳解决方案。所以这种方法有几个好处:

  1. 无论服务器将您作为数据发送给您,它都不会崩溃
  2. 所有变量的默认值等于nil
  3. 您无需考虑业务逻辑以及适合您需求的默认值
  4. 但是,使用此方法存在一个缺点:某些属性与您的逻辑永远不会是nil将具有nil初始值。因此,您需要添加验证以展开可空属性。

    选项3 向变量类型添加显式解包,var id : Int!。请注意,这也会将nil作为初始值添加到您的属性中,但会告诉编译器,在每次使用它们时,它们都不会是nil。我个人不推荐这种方法,因为如果没有从服务器收到变量,或者解析失败,或者其他意外情况发生,那么你的应用程序将会崩溃found nil while unwrapping optional value。作为参考,您可能已经注意到所有IBOutlets都是以这种方式定义的。

    说了这么多,我建议你选择最适合服务器通信的选项2 ,但选择权是你的!

    快乐的编码。

答案 1 :(得分:0)

我找到了两个问题的解决方案。感谢@ dvp.petrov。

解决方案1 ​​var profile : Profile!非常方便,但如果这不是一个可选变量并且必须在许多地方使用,那就很难了。每次都必须进行大量检查并打开包装。当一个人必须在非常少的地方使用它时,这很容易使用

解决方案2:创建一个init函数,为所有变量提供默认值,然后您可以创建var profile : Profile()。这样您的对象就不会是nil,并且可以在某些地方使用它。

struct Profile : Codable {
    var id : Int
    var name : String
    var member_id : Int

   init() {
    self.id = 0
    self.name = ""
    self.member_id = 0

}