我的委托函数正在被调用,但我的 UI 仍然没有相应更新
My delegate function IS being called, still my UI does not update accordingly
我的委托模式有效(如果我的委托函数只需要打印关于传回数据的语句)(编程布局,没有 IB segues)。但是接收器 class 不会相应地更新其 UI。这——我相信——结束了这个案子,我的授权模式是错误的。
我的 UI 怎么可能没有更新?什么情况通常会阻止这种情况?我在这里处理手动条目,没有网络调用,没有大量数据或类似的东西。
例如我的委托函数是:
class DetailTableViewController: AddVCDelegate {
//delegate function of AddVCDelgate protocol
func didAddLesson(lesson: Lesson) { // my addVC is calling this through delegate
self.lesson = lesson
print("delegate function set navitem title: \(lesson.name!)")//printed out correctly
self.navigationItem.title = lesson.name! //nothing changes
self.tableView.reloadData()// no reload
}
/*Here lesson.name got printed out nicely, navigationItem title does not change accordingly , tableView does not reload data.*/
返回 AddVC ViewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
let vc = DetailTableViewController()
self.delegate = vc //etc..}
并且 AddVC 使用此函数:
func passLesson() {
if let lesson = lesson,
let delegate = self.delegate {
delegate.didAddLesson(lesson: lesson)
}
}
我只是发布了这个小片段,因为项目现在有点太复杂了,无法复制到这里,但我相信这是问题代码的相关部分。如果需要,我可以更新更多细节。提前致谢!
更新:我已经将一个简单的演示项目上传到 GitHub,它正在重现问题,我希望它有助于找出问题的真正原因。我还在拼命寻找,我这里做错了什么。
您是从后台线程调用委托吗?
如果是这样,您需要包装要在主队列上分派的任何 UI 更新调用,如下所示:
func didAddLesson(lesson: Lesson) { // my addVC is calling this through delegate
self.lesson = lesson
print("delegate function set navitem title: \(lesson.name!)")//printed out correctly
DispatchQueue.main.async {
self.navigationItem.title = lesson.name! //nothing changes
self.tableView.reloadData()// no reload
}
}
您正在创建 DetailTableViewController()
的新实例并将其分配给委托对象。您不是在调用视图层次结构中存在的 DetailTableViewController,而是调用一个新视图层次结构。
您需要使用现有的视图控制器分配委托。
澄清:
您在屏幕上显示 DetailTableViewController
。这就是您在调用委托时要更新的视图。我们称之为 View A
.
当您分配委托时,您正在实例化一个新的 DetailTableViewController
,它 不是 View A
,而是您创建的一个新对象'不显示给用户。我们称之为 View B
.
当您执行函数 passLesson()
时,您正在调用 View B
中的方法 didAddLesson()
,该方法未向用户显示。
您不应该创建新的 View B
,您需要在委托中使用 View A
。如何?好吧,您需要以某种方式将 View A
提供给您的 AddVC
class 并将其用于您的代表。
TLDR:let vc = DetailTableViewController()
行是错误的。不要实例化新控制器,使用现有控制器。
好的,我找到解决办法了!
正如@Roberto 和@matt 指出的那样,我创建了一个新的委托实例 VC,因此委托基本上不起作用!我很困惑,因为所有打印语句都在委托函数中工作。但这还不够。
我也把 addVC.delegate = self
放在了错误的方法中!在 addVC class 中将其更改为 self.delgate = detailVC
的想法也是错误的。
正确的答案似乎是 detailVC,当我移动到 AddVC 时,我是这样做的:
@objc func handleEdit() {
let avc = AddVC()
avc.lesson = self.lesson
avc.delegate = self
let nc = UINavigationController(rootViewController: avc)
present(nc, animated: true, completion: nil)
}
这样,在 AddVC 出现时,detailVC 已经 知道,她是代表!为什么?因为我通过这种方式告诉 detailVC,我指的 addVC 是制作 "segue" 的 navigationController 的 rootController。因为 classes 是引用类型,所以 addVC 的新实例将是相同的,并引用原始实例。我希望我的理解是正确的。
但是工作!
我的委托模式有效(如果我的委托函数只需要打印关于传回数据的语句)(编程布局,没有 IB segues)。但是接收器 class 不会相应地更新其 UI。这——我相信——结束了这个案子,我的授权模式是错误的。 我的 UI 怎么可能没有更新?什么情况通常会阻止这种情况?我在这里处理手动条目,没有网络调用,没有大量数据或类似的东西。 例如我的委托函数是:
class DetailTableViewController: AddVCDelegate {
//delegate function of AddVCDelgate protocol
func didAddLesson(lesson: Lesson) { // my addVC is calling this through delegate
self.lesson = lesson
print("delegate function set navitem title: \(lesson.name!)")//printed out correctly
self.navigationItem.title = lesson.name! //nothing changes
self.tableView.reloadData()// no reload
}
/*Here lesson.name got printed out nicely, navigationItem title does not change accordingly , tableView does not reload data.*/
返回 AddVC ViewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
let vc = DetailTableViewController()
self.delegate = vc //etc..}
并且 AddVC 使用此函数:
func passLesson() {
if let lesson = lesson,
let delegate = self.delegate {
delegate.didAddLesson(lesson: lesson)
}
}
我只是发布了这个小片段,因为项目现在有点太复杂了,无法复制到这里,但我相信这是问题代码的相关部分。如果需要,我可以更新更多细节。提前致谢!
更新:我已经将一个简单的演示项目上传到 GitHub,它正在重现问题,我希望它有助于找出问题的真正原因。我还在拼命寻找,我这里做错了什么。
您是从后台线程调用委托吗? 如果是这样,您需要包装要在主队列上分派的任何 UI 更新调用,如下所示:
func didAddLesson(lesson: Lesson) { // my addVC is calling this through delegate
self.lesson = lesson
print("delegate function set navitem title: \(lesson.name!)")//printed out correctly
DispatchQueue.main.async {
self.navigationItem.title = lesson.name! //nothing changes
self.tableView.reloadData()// no reload
}
}
您正在创建 DetailTableViewController()
的新实例并将其分配给委托对象。您不是在调用视图层次结构中存在的 DetailTableViewController,而是调用一个新视图层次结构。
您需要使用现有的视图控制器分配委托。
澄清:
您在屏幕上显示 DetailTableViewController
。这就是您在调用委托时要更新的视图。我们称之为 View A
.
当您分配委托时,您正在实例化一个新的 DetailTableViewController
,它 不是 View A
,而是您创建的一个新对象'不显示给用户。我们称之为 View B
.
当您执行函数 passLesson()
时,您正在调用 View B
中的方法 didAddLesson()
,该方法未向用户显示。
您不应该创建新的 View B
,您需要在委托中使用 View A
。如何?好吧,您需要以某种方式将 View A
提供给您的 AddVC
class 并将其用于您的代表。
TLDR:let vc = DetailTableViewController()
行是错误的。不要实例化新控制器,使用现有控制器。
好的,我找到解决办法了!
正如@Roberto 和@matt 指出的那样,我创建了一个新的委托实例 VC,因此委托基本上不起作用!我很困惑,因为所有打印语句都在委托函数中工作。但这还不够。
我也把 addVC.delegate = self
放在了错误的方法中!在 addVC class 中将其更改为 self.delgate = detailVC
的想法也是错误的。
正确的答案似乎是 detailVC,当我移动到 AddVC 时,我是这样做的:
@objc func handleEdit() {
let avc = AddVC()
avc.lesson = self.lesson
avc.delegate = self
let nc = UINavigationController(rootViewController: avc)
present(nc, animated: true, completion: nil)
}
这样,在 AddVC 出现时,detailVC 已经 知道,她是代表!为什么?因为我通过这种方式告诉 detailVC,我指的 addVC 是制作 "segue" 的 navigationController 的 rootController。因为 classes 是引用类型,所以 addVC 的新实例将是相同的,并引用原始实例。我希望我的理解是正确的。 但是工作!