xcode 串行调度队列未按预期运行

snz8szmq  于 2023-02-20  发布在  其他
关注(0)|答案(1)|浏览(124)

要在我的应用视图中加载一些信息,我需要它来完成联网,因为一些方法依赖于结果。我查看了串行DispatchQueue.async方法,但它没有按预期工作。
以下是我目前尝试的方法。我定义了3个块:
1.在那里我可以获得用户的电子邮件(如果有的话
1.电子邮件将用作名为getData的方法的输入,该方法根据用户的电子邮件地址读取数据库
1.这个块将用数据库中的数据填充表视图。我已经这样布置了它,但是我得到一个错误,告诉我第二个块仍然在我们访问用户的电子邮件地址之前执行,即第一个块已经完成。感谢任何帮助,提前感谢!

let serialQueue = DispatchQueue(label: "com.queue.serial")
        let block1 = DispatchWorkItem {
            GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in
                if error != nil || user == nil {
                    print("unable to identify user")
                } else {
                    print(user!.profile?.email ?? "")
                    self.email = user!.profile?.email ?? ""
                    print("email is: \(self.email)")
                }
            }
        }
        
        let block2 = DispatchWorkItem{
            self.getData(self.email)
        }
        
        let block3 = DispatchWorkItem {
            DispatchQueue.main.async {
                self.todoListTable.reloadData()
            }
        }
        serialQueue.async(execute: block1)
        block1.notify(queue: serialQueue, execute: block2)
        block2.notify(queue: serialQueue, execute: block3)
jaxagkaj

jaxagkaj1#

您的问题是您在工作项内分派异步工作;GIDSignIn.sharedInstance.restorePreviousSignIn立即“返回”,但在工作实际完成后触发完成处理程序。由于它已返回,因此调度队列认为工作项已完成,并继续处理下一项。
传统的方法是从第一个的完成处理程序调用第二个操作(从第二个调用第三个)。
假设您修改了self.getData(),使其具有一个完成处理程序,它将如下所示:

GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in
    if error != nil || user == nil {
        print("unable to identify user")
    } else {
       print(user!.profile?.email ?? "")
       self.email = user!.profile?.email ?? ""
       print("email is: \(self.email)")
       self.getData(self.email) {
           DispatchQueue.main.async {
               self.todoListTable.reloadData()
           }
       }
    }
}

你可以看到你很快结束了一个“厄运金字塔”。
现代的方法是使用async/await,这需要你的函数支持这种方法,并且要求最低iOS级别为iOS 13。
它看起来就像

do {
    let user = try await GIDSignIn.sharedInstance.restorePreviousSignIn()
    if let email = user.profile?.email {
       let fetchedData = try await getData(email)
       self.data = fetchedData
            self.tableView.reloadData()
    }
} catch {
    print("There was an error \(error)")
}

啊。读起来简单多了。

相关问题