UITableView 在调用 reloadData 方法时返回 nil
UITableView returning nil when reloadData method is called upon it
项目信息:
我有三个视图:'Main, AddTask, and TaskTable' 和三个视图控制器:'MainVC, AddTaskVC, TaskTableVC'。
我的 'Main' 视图有一个嵌入的 'UITableView',即 'TaskTable'。
我的 'Main' 视图也有一个按钮,它显示一个模态视图 'AddTask'。
我的 'AddTask' 视图有一个自动关闭的按钮。
我的 'TaskTableVC' 有一个名为 'taskTable' 的对象,它是 'UITableView'
目标:
当模式视图 AddTask
被关闭时,我一直在尝试在 taskTable
上调用 reloadData
。但是,无论我如何解决这个问题,我都无法在 taskTable
上调用 reloadData
,因为在 AddTask
第一次出现后它似乎总是 nil。
问题研究:
我做的第一件事是在 AddTask
被关闭时使用 completion
在我的 taskTable
对象上直接调用 reloadData()
:
self.dismiss(animated: true, completion: {
TaskTableVC().taskTable.refreshData()
})
但我很快了解到我不能直接调用它,因为 TaskTable
视图没有加载并且我正在创建一个实例。
接下来,我在我的 viewDidLoad
上打印了我的三个视图的语句(请参阅项目信息)。启动时,首先加载的是我的 TaskTable
,然后是我的 Main
。当我单击 Main
上的按钮时,我的 AddTask
加载。到目前为止一切顺利...但是,当我关闭 AddTask
时,没有加载任何内容。我以为我的 TaskTable
和 Main
会被加载,但事实并非如此。所以我尝试在 AddTaskVC
中的 dismiss
的 completion
上调用属于 MainVC
的函数 refreshData()
该函数将加载 TaskTable
视图使用loadViewIfNeeded
:
func refreshData() {
TaskTableVC().loadViewIfNeeded()
}
然后在我的TaskTableVC
下我的viewDidLoad
我有:
override func viewDidLoad() {
super.viewDidLoad()
print("table view loaded")
self.taskTable.reloadData()
}
然而我继续得到的错误是:Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
我相信这是因为我通过实例调用了 TaskTableVC.loadViewIfNeeded()
?不管是什么情况,我一辈子都无法让它发挥作用。
TL;DR
当我在模态视图上调用 dismiss 时,我需要在嵌入式 UITableView
上调用 reloadData
。
//MainVC:
class MainVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
print("main view loaded")
}
func refreshData() {
TaskTableVC().loadViewIfNeeded()
}
}
//AddTaskVC
class AddTaskVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
print("AddTask view loaded")
}
//...
@IBAction func addTask(_ sender: Any) {
//...
self.dismiss(animated: true, completion: {
MainVC().refreshData()
})
}
}
//TaskTableVC
class TaskTableVC : UITableViewController {
@IBOutlet var taskTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
print("table view loaded")
self.taskTable.reloadData() //error here
}
//...
}
有几个选项,例如你可以使用Delegate pattern to communicate between those ViewControllers, there are also some other options like Observer pattern or RxSwift,你也可以直接保留一些对那些嵌入的ViewControllers的引用,但我不建议这样做。
由于这些嵌入式 ViewController 之间存在 segue 关系,我们可以使用 prepare(for segue
方法来评估这些委托。
class MainVC: UIViewController, TasksUpdateDelegate {
weak var tasksTableDelegate: TaskTableDelegate?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let taskTableVC = segue.destination as? TaskTableVC {
tasksTableDelegate = taskTableVC
} else if let addTaskVC = segue.destination as? AddTaskVC {
addTaskVC.delegate = self
}
}
func tasksChanged() {
tasksTableDelegate?.reloadTasks()
}
}
TasksUpdateDelegate
通知 MainVC
任务的任何变化。
protocol TasksUpdateDelegate: class {
func tasksChanged()
}
class AddTaskVC: UIViewController {
weak var delegate: TasksUpdateDelegate?
@IBAction func addTask(_ sender: Any) {
dismiss(animated: true) { [weak self] in
self?.delegate?.tasksChanged()
}
}
}
TasksTableDelegate
在MainVC中用于通知TaskTableVC
应该重新加载tasksTable
。
protocol TaskTableDelegate: class {
func reloadTasks()
}
class TaskTableVC: UITableViewController, TaskTableDelegate {
@IBOutlet var taskTable: UITableView!
func reloadTasks() {
taskTable.reloadData()
}
}
项目信息:
我有三个视图:'Main, AddTask, and TaskTable' 和三个视图控制器:'MainVC, AddTaskVC, TaskTableVC'。 我的 'Main' 视图有一个嵌入的 'UITableView',即 'TaskTable'。 我的 'Main' 视图也有一个按钮,它显示一个模态视图 'AddTask'。 我的 'AddTask' 视图有一个自动关闭的按钮。 我的 'TaskTableVC' 有一个名为 'taskTable' 的对象,它是 'UITableView'
目标:
当模式视图 AddTask
被关闭时,我一直在尝试在 taskTable
上调用 reloadData
。但是,无论我如何解决这个问题,我都无法在 taskTable
上调用 reloadData
,因为在 AddTask
第一次出现后它似乎总是 nil。
问题研究:
我做的第一件事是在 AddTask
被关闭时使用 completion
在我的 taskTable
对象上直接调用 reloadData()
:
self.dismiss(animated: true, completion: {
TaskTableVC().taskTable.refreshData()
})
但我很快了解到我不能直接调用它,因为 TaskTable
视图没有加载并且我正在创建一个实例。
接下来,我在我的 viewDidLoad
上打印了我的三个视图的语句(请参阅项目信息)。启动时,首先加载的是我的 TaskTable
,然后是我的 Main
。当我单击 Main
上的按钮时,我的 AddTask
加载。到目前为止一切顺利...但是,当我关闭 AddTask
时,没有加载任何内容。我以为我的 TaskTable
和 Main
会被加载,但事实并非如此。所以我尝试在 AddTaskVC
中的 dismiss
的 completion
上调用属于 MainVC
的函数 refreshData()
该函数将加载 TaskTable
视图使用loadViewIfNeeded
:
func refreshData() {
TaskTableVC().loadViewIfNeeded()
}
然后在我的TaskTableVC
下我的viewDidLoad
我有:
override func viewDidLoad() {
super.viewDidLoad()
print("table view loaded")
self.taskTable.reloadData()
}
然而我继续得到的错误是:Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
我相信这是因为我通过实例调用了 TaskTableVC.loadViewIfNeeded()
?不管是什么情况,我一辈子都无法让它发挥作用。
TL;DR
当我在模态视图上调用 dismiss 时,我需要在嵌入式 UITableView
上调用 reloadData
。
//MainVC:
class MainVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
print("main view loaded")
}
func refreshData() {
TaskTableVC().loadViewIfNeeded()
}
}
//AddTaskVC
class AddTaskVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
print("AddTask view loaded")
}
//...
@IBAction func addTask(_ sender: Any) {
//...
self.dismiss(animated: true, completion: {
MainVC().refreshData()
})
}
}
//TaskTableVC
class TaskTableVC : UITableViewController {
@IBOutlet var taskTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
print("table view loaded")
self.taskTable.reloadData() //error here
}
//...
}
有几个选项,例如你可以使用Delegate pattern to communicate between those ViewControllers, there are also some other options like Observer pattern or RxSwift,你也可以直接保留一些对那些嵌入的ViewControllers的引用,但我不建议这样做。
由于这些嵌入式 ViewController 之间存在 segue 关系,我们可以使用 prepare(for segue
方法来评估这些委托。
class MainVC: UIViewController, TasksUpdateDelegate {
weak var tasksTableDelegate: TaskTableDelegate?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let taskTableVC = segue.destination as? TaskTableVC {
tasksTableDelegate = taskTableVC
} else if let addTaskVC = segue.destination as? AddTaskVC {
addTaskVC.delegate = self
}
}
func tasksChanged() {
tasksTableDelegate?.reloadTasks()
}
}
TasksUpdateDelegate
通知 MainVC
任务的任何变化。
protocol TasksUpdateDelegate: class {
func tasksChanged()
}
class AddTaskVC: UIViewController {
weak var delegate: TasksUpdateDelegate?
@IBAction func addTask(_ sender: Any) {
dismiss(animated: true) { [weak self] in
self?.delegate?.tasksChanged()
}
}
}
TasksTableDelegate
在MainVC中用于通知TaskTableVC
应该重新加载tasksTable
。
protocol TaskTableDelegate: class {
func reloadTasks()
}
class TaskTableVC: UITableViewController, TaskTableDelegate {
@IBOutlet var taskTable: UITableView!
func reloadTasks() {
taskTable.reloadData()
}
}