Swift UITableViewController `await`直到所有数据加载完毕后再进行渲染,或者在数据加载完毕后重新渲染。

问题描述 投票:0回答:1

我使用的是Swift 4。我们的目标是加载地址簿中的所有数据,然后再在视图中呈现地址簿。在不同的语言中,如 js,我可以用 await 中的每一个项目,然后再告诉视图渲染行。我正在寻找解决这个问题的规范方法,在 Swift 4UITableViewController.

现在,通讯录存储在后台,并有 AmplifyGraphQL. 我有一个 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-token,然后我用这个创建一个对象 contact 信息。然后对每个 Contact 对象实例,我得到了它对应的 User 在数据库中,当对象被初始化时。根据这篇文章。等到带有异步网络请求的swift for循环完成执行后,我使用的是 Dispatch 组,然后重新加载 UITableView 循环完成后,在 Dispatch 组已经结束。但当我 print 到控制台,我看到循环完成之前的 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")
                }
            }
        }


    }
ios swift uitableview graphql
1个回答
0
投票

这是因为该函数 getMyContacts() 正在执行一个Async任务,而控件会越过这个任务执行leave语句。你需要在 getMyContacts() 函数在for循环之外。

试试下面的代码。

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()
            }


            fetchContactGrp.wait()

            DispatchQueue.main.async{
                 self.tableView.reloadData()
            }
        }

0
投票
© www.soinside.com 2019 - 2024. All rights reserved.