如何连接 DispatchGroup 和 Executed Request Alamofire?

How connect DispatchGroup and Executed Request Alamofire?

我有一个简单的线程任务,但似乎对其他人都有帮助的东西对我不起作用,我不明白为什么。

这是我的按钮处理:

AnyButton(action: {
                    if isPhoneMode {
                        
                        print("starting long running tasks")
                        let group = DispatchGroup()
                        group.enter()
                        DispatchQueue.global().async {
                            urlService.loginRequest(login: "+\(countryCode)\(phoneNumber)", password: password, completion: {
                                print("print in complition")
                            })
                            print("long task done!")
                            group.leave()
                        }
                        group.notify(queue: DispatchQueue.global()) {
                            print("all tasks done!")
                        }
                        
                    }

这是loginRequest:

func loginRequest(login: String, password: String, completion: @escaping () -> Void) {
    let parameters: Parameters = [
        "language": "EN",
        "password": password,
        "username": login
    ]
    let url = "someURL"
    let authRequest = AF.request(url,
                                 method: .post,
                                 parameters: parameters,
                                 encoding: JSONEncoding.default)
    authRequest.responseString { response in
        switch response.result {
        case .success(let value):
            let responseArr = value.components(separatedBy: "\u{0022}")
            if responseArr[11] == "ACTIVE" {
                self.loginStatus = .correctLogin
                print("correct login!")
            }
        case .failure(let error):
            print("Error: \(String(describing: error))")
            self.loginStatus = .requestFail
        }
    }
    completion()
}

group.notify 无法正确跟踪我的请求。正确的登录始终在控制台中持续:为什么这样?

starting long running tasks 
print in complition 
long task done! 
all tasks done! 
correct login!

我希望它在“long task done”之前。我该怎么做?

首先你误用了DispatchGroup。正如名称 group 暗示它用于多项任务,但您只执行一项任务。

意外行为的原因是leave命令在完成闭包之外。所以leave会被立即执行,群调用notify

如果没有 DispatchGroup

,这会达到您的预期
AnyButton(action: {

    if isPhoneMode {
        
        print("starting long running tasks") // actually one task
        DispatchQueue.global().async {
            urlService.loginRequest(login: "+\(countryCode)\(phoneNumber)", password: password, completion: {
                DispatchQueue.main.async {
                    print("print in completion")
                    print("long task done!")
                }
            })
        }
    }

你问:

“Correct login” always last in console: Why so?

因为您对完成处理程序的调用不在正确的位置。例如

func loginRequest(login: String, password: String, completion: @escaping () -> Void) {
    …

    authRequest.responseString { response in
        switch response.result { … }

        completion()                       // Move `completion` here
    }

    // completion()                        // It should not be here
}

您的调度组中有类似的问题,即 leave 属于完成处理程序:

AnyButton(action: {
    if isPhoneMode {
        print("starting long running tasks")
        
        let group = DispatchGroup()
        group.enter()
        
        urlService.loginRequest(login: "+\(countryCode)\(phoneNumber)", password: password) {
            print("print in completion")
            
            group.leave()                 // Move `leave` here
        }
        
        print("long task done!")
        
        // group.leave()                  // not here
        
        group.notify(queue: DispatchQueue.global()) {
            print("all tasks done!")
        }
    }
})

注意,我已经删除了对全局队列的冗余调度(因为 loginRequest 已经异步运行)。

但是因为你只有一个任务,调度组也是多余的。仅当您有多个任务需要在完成时得到通知时才使用组。不过,在这种情况下,它是句法噪音。因此,这可以进一步简化为:

AnyButton(action: {
    if isPhoneMode {
        print("starting long running tasks")
        
        urlService.loginRequest(login: "+\(countryCode)\(phoneNumber)", password: password) {
            print("print in completion")
        }
    }
})