问题描述
先谢谢您。我正在使用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 数据并显示出来。
一些观察结果:
-
您不想使
checkContacts
的“完成处理程序”逻辑与您可能在函数中使用的调度组纠缠在一起。如果您发现自己绕过了调度组对象,则通常表明您不必要地纠缠了方法。因此,如果您需要
checkContacts
中的调度组,可以使用它,但不要因此而给呼叫者带来麻烦。只需使用完成处理程序关闭模式即可。 -
确保在异步过程完成之前不要更新模型对象。
例如:
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()
}