Bring item from an API in Swift

Asked

Viewed 196 times

0

I am consuming a Json API and need to bring only one of the objects that it returns to me, but I am not getting, I am trying the following code:

let httpStatus = response as? HTTPURLResponse
if httpStatus?.statusCode == 200 {
if data?.count != 0 {
    let respJson = try! JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! NSArray
    if let codigo = respJson ["codigo" as! Int]{
        print("Codigo: \(codigo)")
        DispatchQueue.main.sync {}
    }
}
  • ["codigo" as! Int] It’s completely wrong. There’s no force cast string for Int to work. It will crash your app every time. The correct is if let codigo = respJson["codigo"] as? Int {. Another thing is that you should cast your json result for a dictionary and not a Nsarray. if let data = data, let respJson = (try? JSONSerialization.jsonObject(with: data)) as? [String: Any] {. And make sure your json even contains a dictionary like top level Object, if it’s an array of dictionaries the json cast would be for [[String: Any]] and you would have to change the way to get your code too.

2 answers

0

It’s not because there’s a key missing in the code?

let httpStatus = response as? HTTPURLResponse
if httpStatus?.statusCode == 200 {
    if data?.count != 0 {
        let respJson = try! JSONSerialization.jsonObject(with: data!, options: .allowFragments) as! NSArray
        if let codigo = respJson ["codigo" as! Int]{
            print("Codigo: \(codigo)")
            DispatchQueue.main.sync {}
        }
    }
}
  • No friend, I copied the code and forgot some keys even, the problem is not that.

0

Response taken into account published code here. Your problem is that you’re running an unsynchronized method so when Voce Tenth print the result after starting your get the result kinda Naoto establishment available. What you need to do is move your print to the closure of your non-synchronized method and add an Handler Completion to your Indicator method and pass the result when finished from inside your closure:

Note: As Voce did not post your JSON I have no way of knowing if it contains one or more terminations. If it contains more than one Cvoce you have to do the sum inside the contained loop of the dictionaries and call the Completion Handler after the loop is completed.

func indicadores(completion: @escaping (_ qdeRescisao: Int?, _ error: Error?) -> Void) {
    let headers = [
        "Content-Type": "application/json",
        "Authorization":"\(UserDefaults.standard.string(forKey: "correctToken")!)"
    ]
    var request = URLRequest(url: URL(string: "http://10.1.80.106:9000/api/indicadores")!)
    request.httpMethod = "GET"
    request.allHTTPHeaderFields = headers
    URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data else {
            completion(nil, error)
            return
        }
        do {
            if let dictionaries = (try JSONSerialization.jsonObject(with: data)) as? [[String: Any]] {
                for dictionary in dictionaries {
                    if let codigo = dictionary["codigo"] as? String, codigo == "rescisao", let qdeRescisao = dictionary["quantidade"] as? Int {
                        completion(qdeRescisao, nil)
                    }
                }
            }
        } catch {
            completion(nil, error)
            return
        }
    }.resume()
}

How to make the method call not synchronized with the Handler Completion:

indicadores { qdeRescisao, error in
    guard let qdeRescisao = qdeRescisao else {
        print(error?.localizedDescription ?? "nil")
        return
    }
    self.qtdTotalRescisao += qdeRescisao
    print("qtdTotalRescisao:", self.qtdTotalRescisao)
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.