Alamofire completionHandler of responseJSON未被调用

时间:2016-01-09 07:44:58

标签: ios swift alamofire

我有以下代码来获取对评论列表的回复。 (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被卡住了,这很奇怪,因为整个功能都是异步的。

2 个答案:

答案 0 :(得分:2)

我遇到过类似的问题:

在主UI线程上,调用:

dispatch_semaphore_wait(loginDoneSemaphore, DISPATCH_TIME_FOREVER)

并使用Alamofire拨打http,内部也使用您的httpRequest.responseJSON

- &GT;终于在responseJSON完成处理程序中找到了代码,从不调用

- &GT;导致在DISPATCH_TIME_FOREVER之后找不到代码

- &GT;终于找到根本原因是:Alamofire的responseJSON,默认情况下,如果你没有传入线程/队列,将在主UI线程上运行

- &GT;在调用Alamofire之前,在主UI线程内部,使用DISPATCH_TIME_FOREVER锁定UI线程

- &GT;因此,遵循Alamofire的responseJSON,也在主UI线程上运行,永远不会调用

- &GT;我的解决方案是:指定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]
})

这对你来说可能很有用。

- &GT;也许你可以使用我的方法:为Alamofire的responseJSON设置另一个线程来解决你的问题。

答案 1 :(得分:0)

我不熟悉Alamofire内部,但它似乎可以在同一个串行队列中完成所有响应completionBlocks。您的dispatch_group_wait阻止其他回复完成并致电dispatch_group_leave

您可以使用dispatch_group_notify而不是dispatch_group_wait来解决此问题,因此,无需阻止该线程,只需在必要时将该块提交到队列。