【问题标题】:Why is my delegate not working even when I complete all of the necessary steps?为什么即使我完成了所有必要的步骤,我的代理人也无法工作?
【发布时间】:2019-12-08 10:23:13
【问题描述】:

我正在尝试使用委托将数据数组传递给前一个视图控制器。我决定使用委托,因为我的放松转场不起作用(更多关于 previous Stack Overflow post 的内容)。我已经创建了代理来执行所有必要的设置步骤。

我尝试了this Stack Overflow question 的一些解决方案,但很多答案都是针对我已经完成的事情。我尝试过的事情:

  • 重命名协议。
  • 重命名代理。
  • 使协议不是class 类型。
  • 强制解包委托(这个很有趣 - 它导致我的应用程序崩溃,即使我知道委托存在)。

我在ViewControllerB中创建了协议:

protocol ViewControllerBDelegate: class {
    func viewControllerB(_ controller: UIViewController, didSelectArray array: [String])
}

我为具有弱引用循环的委托创建了一个变量:

weak var viewControllerBDelegate: ViewControllerBDelegate?

我还从didSelectRowAt 中的代表那里调用了一个函数:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let strArray = ["Hello", "World"]
    viewControllerBDelegate?.viewControllerB(self, didSelectArray: strArray)
}

然后在ViewControllerA:

class ViewControllerA: UIViewController, ViewControllerBDelegate

在 ViewControllerB 委托函数中:

func viewControllerB(_ controller: UIViewController, didSelectArray array: [String]) {
    print("An array of strings: \(array)")

    controller.dismiss(animated: true, completion: nil)
}

在准备转场功能中:

if let viewControllerB = segue.destination as? ViewControllerB {
    viewControllerB.viewControllerBDelegate = self
}

我希望委托打印 ViewControllerB 传递的数组的内容。但它不起作用,而且与我的代码的目标不同,视图控制器并没有像预期的那样关闭。

【问题讨论】:

  • 有点建设性的批评?我刚刚评论了你的另一个问题——你使用 Xcode 11 beta 有什么原因吗?你想使用UIKit,对吗?在 Xcode 10 中,代理和 Storyboard 展开都为我工作。如果您的目标不是 UIKit,我不知道(并且可能是错误的)有任何理由使用 Xcode 10。我觉得你把事情复杂化了。让某些东西在 Xcode 10 和 iOS 12(或更早版本)中运行,然后使用测试版。
  • “强制解包代理......导致我的应用程序崩溃”......好吧,所以你已经缩小到viewControllerBDelegate显然是nil这一事实。所以问题是为什么。因此,请在您的 prepare(for:sender:) 中添加一个断点,并确保您到达了该行。如果没有,也许您展示了第二个视图控制器而不是对其执行 segue?也许第二个视图控制器嵌入在导航控制器中?根据提供的信息无法判断,但很可能是这样的。
  • 无关的,你打电话给controller.dismiss(animated: true, completion: nil)。请注意,从技术上讲,应该在呈现的视图控制器上调用dismiss,而不是在呈现的视图控制器上。 “呈现视图控制器负责解除它呈现的视图控制器。如果你在呈现的视图控制器本身上调用此方法,UIKit 会要求呈现视图控制器处理解除。”因此,您可以简化并直接调用 dismiss(animated: true),而不是 controller.dismiss(animated: true)。(注意,这与手头的问题无关,只是一个 FYI。)
  • @dfd 我正在使用 Xcode 11 测试版,因为我想为 iOS 13 做准备。我需要使用 iOS 13 SDK。如果 unwind segues 在那里工作,我可能只需要切换回 Xcode 10。
  • @Rob 我忘了提到 ViewControllerB 以模态方式呈现并嵌入在导航控制器中。当我对 ViewControllerB 执行 segue 时,我忘记包含有关导航控制器的代码。这解决了它,

标签: ios swift delegates


【解决方案1】:

你说:

强制解包委托...导致我的应用崩溃

这缩小了viewControllerBDelegate 显然为零的事实。所以问题是为什么。所以,在你的prepare(for:sender:) 中添加一个断点,并确保你到达了那一行。如果没有,也许您提供了第二个视图控制器而不是对其执行 segue?也许第二个视图控制器嵌入在导航控制器中?根据最初提供的信息无法判断,但很可能是这样的。

在 cmets 中,您已确认第二个视图控制器嵌入在导航控制器中。我知道你已经弄清楚了,但为了未来的读者,在这种情况下,prepare(for:sender:) 可能看起来像:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let nav = segue.destination as? UINavigationController,
        let controller = nav.topViewController as? ViewControllerB {
            controller.delegate = self
    }
}

请原谅我将委托属性的名称更改为简单的delegate。按照惯例,我总是使用delegate,除非在极少数情况下我需要在两个不同的委托协议之间消除歧义。但希望这能说明这个想法。

【讨论】:

    【解决方案2】:

    您创建一个weak 对委托的引用。如果委托(包括 UIKit 员工)上没有其他内容不引用,则 ARC 将删除它。如果是真的,你应该删除weak 修饰符。

    您可以在https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html 阅读有关 ARC 的信息

    您的应用会出现以下情况:

    1. App 呈现 viewControllerA
    2. 应用转换到 viewControllerB
    3. App 将 viewControllerA 作为委托 viewControllerB
    4. 应用关闭 viewControllerA

    现在,viewControllerB 的委托等于nil

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-08
      • 2021-11-27
      • 1970-01-01
      • 1970-01-01
      • 2017-05-21
      • 1970-01-01
      • 2016-04-21
      • 1970-01-01
      相关资源
      最近更新 更多