【问题标题】:iOS swift - working with response from APIiOS swift - 处理来自 API 的响应
【发布时间】:2019-04-25 05:43:14
【问题描述】:

我对 Swift 和 iOS 开发非常陌生。如果我使用 JavaScript,我想知道如何做一些相对简单的事情。

我正在调用返回以下内容的 API。请原谅格式化,但它是直接从 Xcode 控制台复制的。

["type": success, "value": <__NSArrayI 0x600000030340>(
       {
          categories = ();
          id = 155;
          joke = "Chuck Norris does not &quot;style&quot; his hair. It lays perfectly in place out of sheer terror.";
       },
       {
            categories = (nerdy);
            id = 69;
            joke = "Scientists have estimated that the energy given off during the Big Bang is roughly equal to 1CNRhK (Chuck Norris Roundhouse Kick).";
       }
    )
]

我想遍历响应并添加到数组中。在 JavaScript 中,它如下所示:

let jokes = [];
response.value.forEach(item => {
   jokes.push(item.joke)
})

不必与上述完全相同。我有信心快速使用循环并附加到数组中。我正在努力做的是访问从 API 返回的 value 数组中的笑话。

我的控制器如下所示:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let url = URL(string: "http://api.icndb.com/jokes/random/2")
        URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
            guard let data = data, error == nil else { return }
            do {
                let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String:Any]
                print(json["value"])
                // not sure how to access each joke in the array here
            } catch let error as NSError {
                print(error)
            }
        }).resume()
    }
}

【问题讨论】:

  • 这在 JS 中很容易,而且在 Swift 中还有额外的工作,因为你处于类型化行为和非类型化行为之间的边界。 JS & JSON - 无类型。 Swift 想在读取 JSON 时添加一些类型; Any 没有强制转换就不是那么有用。有几个框架可以提供帮助(例如 SwiftyJSON),Swift 本身也添加了 Codable/Decodable。
  • 太好了,知道@GrahamPerks 真是太好了。只是一个问题 - 假设基于生产 Web React 的应用程序可能会进行大量 API 调用并将这些数据存储在 redux 存储中。 iOS 开发是否有一些类似的方法,或者我应该注意什么?
  • 这完全是另一个问题......我通常采用两种方法之一。解析并将下载的数据插入 SQLite,如果我需要它持久。或者像 redux 一样将其存储在 RAM 中,例如使用单例 JokeManager 类,它可以将 JSON 派生的字典 [String:Any] 解析为一些有用的 Swift 对象。然后用户界面或任何可以根据需要从JokeManager.shared 中提取笑话。
  • 这肯定是另一个问题,但感谢您的回答。给了我一些研究:-D——但你建议的是用于生产应用程序的方法?
  • 顺便说一句,SwiftyJSON 看起来很棒

标签: ios json swift nsjsonserialization


【解决方案1】:

你可以试试

if let va = json["value"] as? [[String:Any]] {
   va.forEach { print($0["joke"]) }
}

我更愿意为此写一个Codable 结构

struct Root: Codable {
    let type: String
    let value: [Value]
}

struct Value: Codable {
    let categories: [Category]
    let id: Int
    let joke: String
}

struct Category: Codable {
}

let res = try? JSONDecoder().decode(Root.self,from:data)
print(res.value)

【讨论】:

  • 谢谢。这在 iOS/swift 中不是很常见的任务吗?就像在 Web 开发中一样。是否有不同的方法来获取我不知道的移动应用程序中使用的数据?另外,您介意告诉我您将如何采用struct 方法吗?
【解决方案2】:

正如您从日志中看到的,变量 json["value"] 的类型为 NSArray,因此您可以执行类似的操作来获取数据(有很多方法可以做到这一点)。

首先你可以像这样创建你想要的对象笑话

class Joke: NSObject {
     var categories = [String]()
     var id: Int?
     var joke: String?

     init(json: [String: Any]) {
         if let categories = json["categories"] as? String {
             for category in categories {
                 self.categories.append(category)
             }
         }
         if let id = json["id"] as? Int {
             self.id = id
         }
         if let joke = json[""] as? String {
             self.joke = joke
         }
     }
}

然后在 ViewController 中执行此操作

class ViewController: UIViewController {


    var jokes = [Joke]()

    override func viewDidLoad() {
        super.viewDidLoad()

        let url = URL(string: "http://api.icndb.com/jokes/random/2")
        URLSession.shared.dataTask(with:url!, completionHandler: {(data, response, error) in
            guard let data = data, error == nil else { return }
            do {
                let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String:Any]
                print(json["value"])
                // not sure how to access each joke in the array here
                let arrayOfObject = json["value"] as! NSArray
                for object in arrayOfObject {
                    if let json = object as? [String: Any] {
                        let object = Joke(json: json)
                        // Now you have your object containing the data from the JSON and you can insert it in your array of Object
                        jokes.append(object)
                    }
                }
            } catch let error as NSError {
                print(error)
            }
        }).resume()
    }
}

请记住,有很多方法可以做到这一点,我向您展示了一种简单的方法,希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-10
    • 2021-03-26
    • 2015-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多