我的委托函数正在被调用,但我的 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,它正在重现问题,我希望它有助于找出问题的真正原因。我还在拼命寻找,我这里做错了什么。

github.com/gerkov77/DataPassing/tree/master

您是从后台线程调用委托吗? 如果是这样,您需要包装要在主队列上分派的任何 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 的新实例将是相同的,并引用原始实例。我希望我的理解是正确的。 但是工作!