用 var 初始化 Codable 结果

initialise Codable result with var

我需要在 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,因为我需要执行操作并稍后在其他代码中访问它。

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

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

为此,您有多种选择。我会列出它们并评论选择哪个以及为什么。

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

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

  1. 无论服务器向您发送什么数据,它都不会崩溃
  2. 所有变量的默认值等于 nil
  3. 您无需考虑您的业务逻辑以及什么默认值适合您的需求

但是,使用这种方法有一个缺点:一些根据您的逻辑永远不可能 nil 的属性将具有 nil 初始值。因此,您需要添加验证以展开可为 null 的属性。

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

综上所述,我建议您使用最适合服务器通信的选项 2,但选择权在您!

编码愉快。

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

解决方案 1 var profile : Profile! 很方便,但如果这不是一个可选变量并且必须在很多地方使用,就会变得困难。每次都必须放很多支票并打开它。当需要在极少的地方使用时,这很容易使用

解决方案 2:创建一个初始化函数,为所有变量提供默认值,然后您可以创建 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

}