簡體   English   中英

Alamofire completionHandler of responseJSON未被調用

[英]Alamofire completionHandler of responseJSON is not called

我有以下代碼來獲取對評論列表的回復。 (1條評論有很多回復)

static func fetchCommentsAndTheirReplies(articleId: String, failure: (()->Void)?, success: (comments: [[String: AnyObject]], replies: [[[String: AnyObject]]], userIds: Set<String>)->Void) {
    var retComments = [[String: AnyObject]]()
    var retReplies = [[[String: AnyObject]]]()
    var retUserIds = Set<String>()

    Alamofire.request(.GET, API.listComment, parameters: [API.articleId: articleId]).responseJSON {
        response in
        guard let comments = response.result.value as? [[String: AnyObject]] else {
            failure?()
            return
        }
        print(comments)
        retComments = comments

        let group = dispatch_group_create()

        for (commentIndex, comment) in comments.enumerate() {
            guard let id = comment["_id"] as? String else {continue}

            let relevantUserIds = parseRelaventUserIdsFromEntity(comment)
            for userId in relevantUserIds {
                retUserIds.insert(userId)
            }

            retReplies.append([[String: AnyObject]]())

            dispatch_group_enter(group)
            Alamofire.request(.GET, API.listReply, parameters: [API.commentId: id]).responseJSON {
                response in
                if let replies = response.result.value as? [[String: AnyObject]] {
                    for (_, reply) in replies.enumerate() {

                        let relevantUserIds = parseRelaventUserIdsFromEntity(reply)
                        for userId in relevantUserIds {
                            retUserIds.insert(userId)
                        }
                    }
                    //TODO: need to capture commentIndex?
                    retReplies[commentIndex] = replies
                }
                dispatch_group_leave(group)
            }


        }

        dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
        success(comments: retComments, replies: retReplies, userIds: retUserIds)
    }
}

永遠不會調用API.listReply請求的完整處理程序。 dispatch_group_enter(group)被調用一次,並且從不調用dispatch_group_leave(group)。 代碼卡在dispatch_group_wait 奇怪的是,即使UI被卡住了,這也很奇怪,因為整個函數都是異步的。

我遇到過類似的問題:

在主UI線程上,調用:

dispatch_semaphore_wait(loginDoneSemaphore, DISPATCH_TIME_FOREVER)

並使用Alamofire調用http,內部也使用您的httpRequest.responseJSON

- >最后發現代碼里面的responseJSON完成處理程序從未調用過

- >因為從未調用過DISPATCH_TIME_FOREVER后找到代碼

- >最后找到根本原因是:Alamofire的responseJSON,默認情況下,如果沒有傳入線程/隊列,將在主UI線程上運行

- >在調用Alamofire之前,有內部主UI線程,要使用DISPATCH_TIME_FOREVER鎖定UI線程

- >所以遵循Alamofire的responseJSON,它也在主UI線程上運行,永遠不會調用

- >我的解決方案是:指定Alamofire在另一個線程上做http響應:

let BackgroundThread:dispatch_queue_t = dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)

func dispatchBackground_async(thingsTodo:()->()) {
    dispatch_async(BackgroundThread, thingsTodo)
}

dispatchBackground_async({
    httpRequest.responseJSON(queue: BackgroundThread, completionHandler: { response in
        gLog.debug("request=\(response.request), response=\(response.response), statusCode=\(response.response?.statusCode), result=\(response.result)")
        // [Debug] [com.apple.root.background-qos] [CrifanLibHttp.swift:21]
})

這對你來說可能很有用。

- >也許你可以使用我的方法:為Alamofire的responseJSON設置另一個線程來解決你的問題。

我不熟悉Alamofire內部,但它似乎可以在同一個串行隊列中完成所有響應completionBlocks。 您的dispatch_group_wait阻止其他響應完成並調用其dispatch_group_leave

您可以使用dispatch_group_notify而不是dispatch_group_wait來解決此問題,因此它不會阻塞線程,而是在必要時將塊提交到隊列。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM