功能中的Swift Dispatch组

问题描述

先谢谢您。我正在使用UITableView,并且需要在加载单元格之前创建一个数组。我正在尝试使用dispatchGroup,成功创建了第一个数组,但是没有创建第二个数组,该数组也需要有效的PhonesNotUsingApp,但未创建相同的函数

我遗漏了整个文件的一部分。

谢谢。

override func viewDidLoad() {
    super.viewDidLoad()
    let group = dispatchGroup()
    setUpElements()
    group.enter()
    checkContacts(group)
    group.notify(queue: .main){
            self.tableView.dataSource = self
            self.tableView.delegate = self
            self.searchBar.delegate = self
            self.tableView.keyboarddismissMode = .onDrag
            print(self.validPhonesNotUsingApp)
            self.tableView.register(TableViewCellForContacts.nib(),forCellReuseIdentifier: TableViewCellForContacts.identifier)
          }
     }


func checkContacts(_ group: dispatchGroup){
    let db = Firestore.firestore()
    db.collection("UserProfile").document(UserDataConst.UserUID).getDocument { (DocumentSnapshot1,Error1) in
        if Error1 != nil{
            print("Error finding if contacts uploaded")
            group.leave()
        }
        else{
            let hasContacts: Bool = DocumentSnapshot1?.get("Contacts Uploaded") as? Bool ?? false
            if hasContacts == true{
                db.collection("UserProfile").document(UserDataConst.UserUID).collection("ContactFriends").getDocuments { (
                    Snapshot2,Error2) in
                    if Error2 != nil{
                        group.leave()
                        return
                    }
                    else{
                        for x in 0..<Snapshot2!.documents.count{
                            group.enter()
                            let validNumber = self.correctPhoneNumber(Snapshot2!.documents[x].documentID,group)
                            if validNumber != nil{
                                self.validPhoneNumbers.append(validNumber!)
                                let first = Snapshot2!.documents[x].get("First Name") as? String ?? "(ø)"
                                self.validPhoneFirstName.append(first)
                                let last = Snapshot2!.documents[x].get("Last Name") as? String ?? "(ø)"
                                self.validPhoneLastName.append(last)
                                
                            }
                            else{
                            group.leave()
                            }
                        }

                        
                        db.collection("AllPhoneNumbers").getDocuments { (Snapshot3,Error3) in
                            if Error3 != nil{
                                group.leave()
                                return
                            }
                            else{
                                print("OK lemme kNow what sup")
                                let docs = Snapshot3!.documents
                                group.enter()
                                for x1 in 0..<self.validPhoneNumbers.count{
                                    group.enter()
                                    var found = false
                                    for x2 in 0..<docs.count{
                                        group.enter()
                                        if self.validPhoneNumbers[x1] == docs[x2].documentID{
                                            let uid = docs[x2].get("UID") as! String
                                            db.collection("UserProfile").document(UserDataConst.UserUID).collection("Friends").getDocuments { (QuerySnapshot4,Error4) in
                                                if Error4 != nil{
                                                    group.leave()
                                                    return
                                                }
                                                else if QuerySnapshot4!.documents.count != 0{
                                                    var found2 = false
                                                    for x3 in 0..<QuerySnapshot4!.documents.count{
                                                        group.enter()
                                                        if QuerySnapshot4!.documents[x3].documentID == uid{
                                                            found2 = true
                                                            //group.leave()
                                                            break
                                                        }
                                                        else{
                                                        group.leave()
                                                        }
                                                    }
                                         
                                                    if found2 == false{
                                                        self.UIDsUsingApp.append(uid)
                                                    }
                                                }
                                                else{
                                                    self.UIDsUsingApp.append(uid)
                                                }
                                            }
                                            //self.UIDsUsingApp.append(uid)
                                            found = true
                                            //group.leave()
                                            break
                                        }
                                    }
                                    if found == false{
                                        self.validPhonesNotUsingApp.append(self.validPhoneNumbers[x1])
                                        self.validFirstNotUsingApp.append(self.validPhoneFirstName[x1])
                                        self.validLastNotUsingApp.append(self.validPhoneLastName[x1])
                                        group.leave()
                                    }
                                    print("OK Now we getting activ")
                                }
                                //print(self.UIDsUsingApp)
                            }
                        }
                        
                    }
                }
            }
            else{
                group.leave()
                return
            }
        }
    }
}

解决方法

我正在使用UITableView,并且需要在加载单元格之前创建一个数组。我正在尝试使用DispatchGroup

好吧,不要。您“在加载单元之前”无法执行任何操作。不要将表处理与调度混合在一起。而且不要以这种方式使用调度组。

关于表视图的所有操作必须立即并在主队列上完成。您可以直接在主队列上的viewDidLoad中注册。您立即在cellForRowAt:中返回一个单元格。您不会与调度组“等待”或以任何其他方式“等待”。

如果您要花费大量时间为表收集数据,那就好了;在后台队列上执行那个,并更新数据模型,然后重新加载表(在主队列上)。所以:

  • 最初,如果数据尚未准备好,则您的数据源方法会发现没有数据,并且会显示一个空表。

  • 稍后,一旦您收集了数据并告诉表视图重新加载,您的数据源方法就会在其中找到 is 数据并显示出来。

,

一些观察结果:

  1. 您不想使checkContacts的“完成处理程序”逻辑与您可能在函数中使用的调度组纠缠在一起。如果您发现自己绕过了调度组对象,则通常表明您不必要地纠缠了方法。

    因此,如果您需要checkContacts中的调度组,可以使用它,但不要因此而给呼叫者带来麻烦。只需使用完成处理程序关闭模式即可。

  2. 确保在异步过程完成之前不要更新模型对象。

例如:

func checkContacts(completion: @escaping (Result<[Contact],Error>) -> Void) {
    let group = DispatchGroup()
    var contacts: [Contact] = []            // in this method,we will only update this local variable

    ...

    group.notify(queue: .main) {
        if let error = error {
            completion(.failure(error))
        } else {
            completion(.success(contacts))  // and when we’re done,we’ll report the results
        }
    }
}

您会这样称呼

checkContacts { results in
    switch results {
    case .failure(let error): 
        ...

    case .success(let contacts):
        self.contacts = contacts            // only now will we update model properties
        ...                                 // do whatever UI updates you want,e.g.
        self.tableView.reloadData()
}