简体   繁体   中英

closure inside completion handler of URLSession.shared.dataTask

I have a call to a closure inside a URLSession.shared.dataTask task. The thing is that when I set a breakpoint inside my closure it won't finish executing.

func query(url: String, args: [String:String], completion: @escaping (_ data: Data) -> Void) {
// Create request url in order to query API.
let url = makeGetRequestUsing(url: url, args: args)
let task = URLSession.shared.dataTask(with: url!) { data, response, error in
    guard let data = data, error == nil else {
        print("error:", error ?? "")
        return
    }
    completion(data)
}

task.resume()

And this is how I call it.

self.comments = []
api.query(url: url, args: args) { data in
    let jsonData = try! JSONSerialization.jsonObject(with: data)
    print(String(data: data, encoding: .utf8))
    if let jsonArray = jsonData as? [[String: Any]] {
        // Create comments from the json received.
        for i in 0..<jsonArray.count {
            do {
                self.comments.append(try Comment(json: jsonArray[i]))
            } catch {
                print(error)
            }
        }
        DispatchQueue.main.async {
            self.refreshComments()
        }
    }
}

I have set a break point inside the completion handler, and it seems that the error comes from the init of Comment class.

init(json: [String: Any]) throws {
// Get the comment text.
guard let comment = json[Comment.commentText] as? String else {
  throw SerializationError.missing(Comment.commentText)
}

// Get userImage.
guard let userId = json[Comment.userId] as? Int,
  let userImage = APIData.shared.getImage(url: "/userImageForId", args: ["id": String(userId)]) else {
    throw SerializationError.missing(Comment.userId)
}

// Get userename.
guard let resp = APIData.shared.getQuery(url: "/userNameForId", args: ["id": String(userId)]) as? [String: String],
  let username = resp[Comment.username] else {
    throw SerializationError.missing(Comment.username)
}

self.comment = comment
self.username = username
self.userImage = userImage

}

The getImage and getQuery are same as the first code. I initiate a task and wait until I get the result using a semaphore.

You say your closure won't finish executing and you also mentioned that you are using a semaphore somewhere in code you haven't posted. It is highly likely that you are using the semaphore incorrectly and that is blocking your thread.

There is nothing in the problem that I can see that warrants using a semaphore in the first place. By bringing in semaphores and exceptions, you seem to be making the code way more complex than necessary.

I suggest you read up on how to unit test code and build up your logic a little at a time. It looks like you are biting off more than you can chew at this time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM