swift 3 numberofrowsinsection 在 vi​​ewwillappear 提取提醒之前运行

swift 3 numberofrowsinsection runs before viewwillappear fetches reminders

想在检索提醒方面寻求帮助。看起来像 numberOfRowsInSection,甚至在 eventStore.fetchReminders 完成之前就被调用了。这是我的代码:

override func viewWillAppear(_ animated: Bool) {
    print("****viewWillAppear")
    super.viewWillAppear(true)
    self.eventStore = EKEventStore()
    self.reminders = [EKReminder]()
    //Added to initialize
    self.reminders.removeAll()
    self.eventStore!.requestAccess(to: EKEntityType.reminder, completion:
        {(granted, error) in
            if granted
            {
                let predicate = self.eventStore.predicateForReminders(in: nil)
                self.eventStore.fetchReminders(matching: predicate, completion: { (reminders: [EKReminder]?) -> Void in
                    self.reminders = reminders
                    DispatchQueue.main.async() {
                        //Added 
                        self.reminders = reminders
                        self.tableView.reloadData()
                    }
                })

            }
            else 
            {
                print("The app is not permitted to access reminders, make sure to grant permission in the settings and try again")
            }
    })

    }
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    print("*****numberOfRowsInSection")
    print("numberOfRowsInSection reminders \(self.reminders.count)")
    return self.reminders.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    print("****titleForHeaderInSection")
    print("titleForHeaderInSection reminders \(self.reminders.count)")
    return "test"
}

我试着把它放在 viewDidLoad 中,但同样的事情发生了,numberofRowsInSection 中的 self.reminders.count 返回 0。我还尝试在 requestAccess 之外调用 fetchReminders(因为我认为 requestAccess 没有触发),但我结束了做同样的事情。我做错了什么吗? 非常感谢任何建议!

谢谢!

这是正常的。 UITableViewController 尝试在显示视图控制器时显示 table 视图的内容。您应该在 viewDidLoad 的开头用空数组初始化 self.reminders,这样 table 视图最初不会显示任何结果。

然后,一旦您完成对事件存储的访问,将调用重置 self.reminders 和重新加载 table 视图的代码。

您应该做的一个重要更改是在 DispatchQueue.main.async() 块中设置 self.reminders。这确保数据源在 table 重新加载之前而不是之前更新。换句话说,将您的代码更新为:

self.eventStore.fetchReminders(matching: predicate, completion: { (reminders: [EKReminder]?) -> Void in
    DispatchQueue.main.async() {
        self.reminders = reminders
        self.tableView.reloadData()
    }
})

要考虑的另一个更改是最初将 self.reminders 设置为 nil 并让您的 table 查看数据源方法将其视为一个信号,以显示一行 "loading"(或类似的东西)。否则,您的用户可能想知道为什么他们会在短时间内盯着几乎空白的屏幕。