Я на Swift 4. Цель состоит в том, чтобы загрузить все данные в адресную книгу, прежде чем отобразить адресную книгу. На другом языке, например js
, я могу использовать await
в каждом элементе в l oop, прежде чем указывать представлению визуализировать строки. Я ищу канонический способ решения этой проблемы в Swift 4
с помощью UITableViewController
.
. Сейчас адресная книга хранится в бэкэнде с Amplify
и GraphQL
. У меня есть User
модель формы
type User @Model {
id: ID!
name: String!
bio : String!
}
и Contact
формы
type Contact @model {
ownerId: ID!
userId: ID!
lastOpened: String
}
В ContactController: UITableViewController.viewDidLoad
Я получаю все Contact
в базе данных, где ownerId
id-токен моего пользователя, затем я создаю объект, используя эту contact
информацию. И затем для каждого Contact
экземпляра объекта я получаю соответствующий User
в базе данных при инициализации объекта. В этом сообщении: Подождите, пока swift для l oop с асинхронными сетевыми запросами не завершит выполнение , я использую группу Dispatch
, а затем перезагрузите UITableView
после завершения l oop и Dispatch
группа закончилась. Но когда я print
утешаю, я вижу, что l oop завершается до того, как объект Contact
загрузил свою User
информацию.
Фрагменты кода:
class ContactsController: UITableViewController, UISearchResultsUpdating {
var dataSource : [Contact] = []
override func viewDidLoad() {
super.viewDidLoad()
let fetchContactGrp = DispatchGroup()
fetchContactGrp.enter()
self.getMyContacts(){ contacts in
for contact in contacts {
let _contactData = Contact(
userId : contact.userId
, contactId : contact.id
, timeStamp : contact.timeStamp
, lastOpened : contact.lastOpened
, haveAccount: true
)
_contactData.loadData()
self.dataSource.append(_contactData)
}
}
fetchContactGrp.leave()
DispatchQueue.main.async{
self.tableView.reloadData()
}
}
}
Функция self.getMyContacts
- это просто стандартный запрос GraphQL
:
func getMyContacts( callBack: @escaping ([Contact]) -> Void ){
let my_token = AWSMobileClient.default().username
let contact = Contact.keys
let predicate = contact.ownerId == my_token!
_ = Amplify.API.query(from: Contact.self, where: predicate) { (event) in
switch event {
case .completed(let result):
switch result {
case .success(let cts):
/// @On success, output a user list
callBack(cts)
case .failure(let error):
break
}
case .failed(let error):
break
default:
break
}
}
}
И объект Contact
загружает данные User
из базы данных:
class Contact {
let userId: String!
let contactId: String!
var name : String
var bio : String
var website: String
let timeStamp: String
let lastOpened: String
init( userId: String, contactId: String, timeStamp: String, lastOpened: String, haveAccount: Bool){
self.userId = userId
self.contactId = contactId
self.timeStamp = timeStamp
self.lastOpened = lastOpened
self.haveAccount = haveAccount
self.name = ""
self.bio = ""
self.website = ""
}
func loadData(){
/// @use: fetch user data from db and populate field on initation
let _ = Amplify.API.query(from: User.self, byId: self.userId) { (event) in
switch event {
case .completed(let res):
switch res{
case .success (let musr):
if (musr != nil){
let userData = musr!
let em = genEmptyString()
self.name = (userData.name == em) ? "" : userData.name
self.bio = (userData.bio == em) ? "" : userData.bio
self.website = (userData.website == em) ? "" : userData.website
print(">> amplify.query: \(self.name)")
} else {
break
}
default:
break
}
default:
print("failed")
}
}
}
}