【问题标题】:UIView to UIViewController communication via protocol not working通过协议的 UIView 到 UIViewController 通信不起作用
【发布时间】:2018-10-10 16:40:25
【问题描述】:

也许我在这里遗漏了一些真正基本的东西,但是在盯着代码一个小时左右之后,我的大脑正在经历循环,我希望能重新审视这个问题。

我有以下UIView

import UIKit

protocol DetailViewWillShowUpDelegate {
    func sendDetailOpened(_ openedBool: Bool)
}

class locationXIBController: UIView {

    @IBOutlet weak var loationLabel: UILabel!
    @IBOutlet weak var vsedniOteviraciDobaLabel: UILabel!
    @IBOutlet weak var prijmajiKartyLabel: UILabel!
    @IBOutlet weak var detailViewButtonOutlet: UIButton!
    @IBOutlet weak var backgroundViewButton: UIButton!

    let openedBool = true
    var detailViewWillShowUpDelegate: DetailViewWillShowUpDelegate?

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    @IBAction func vecerkaDetailButtonPressed(_ sender: UIButton) {
        detailViewWillShowUpDelegate?.sendDetailOpened(openedBool)
        print("pressed")
    }

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        if let result = detailViewButtonOutlet.hitTest(convert(point, to: detailViewButtonOutlet), with: event) {
            return result
        }
        return backgroundViewButton.hitTest(convert(point, to: backgroundViewButton), with: event)
    }

}

现在的问题是,当我调用/按下 vecerkaDetailButtonPressed 函数时,我在控制台中得到“按下”输出,但由于某种原因协议没有通过。

另一面看起来像这样(为简单起见,去掉了):

class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {

    let locationXIB = locationXIBController()
    let isVecerkaDetailOpened = false

    override func viewDidLoad() {
       locationXIB.detailViewWillShowUpDelegate = self
    }



extension MapViewController: DetailViewWillShowUpDelegate {
    func sendDetailOpened(_ openedBool: Bool) {
        isVecerkaDetailOpened = openedBool
        print("success")
    }
}

我知道执行时的协议值为零。正如我所说,感谢任何帮助,谢谢!

【问题讨论】:

  • 那么detailViewWillShowUpDelegate实际上指向任何东西,还是没有?
  • @Caleb 我刚刚调试了一下,其实是nil
  • 您在哪里将locationXIB 添加到您的MapViewController
  • @UpholderOfTruth 感谢您的回复:我不是,locationXIBController 用作自定义MKAnnotation 类,用于自定义MKAnnotationView 类,但是我需要以某种方式连接实例locationXIBController 是通过点击一个地图注释来调用的,并将这个locationXIBController 类的信息发送到MapViewController,你的问题(一个很好的问题)实际上是我要解决的问题
  • 您的LocationInformationAnnotationView 需要有一个委托属性,以便它可以将消息传递给您的MapViewController。如果LocationInformationAnnotationView 包含LocationXIBController,则注释视图应将自己设置为视图委托并将上游传递给委托(地图视图控制器)

标签: ios swift protocols communication hittest


【解决方案1】:

首先,几个命名约定问题:

名称locationXIBControllerUIView 对象的错误选择。它是一个视图对象,而不是控制器对象。

其次,Swift 中的类名应该以大写字母开头。所以LocationXIBView 将是该视图类的更好名称。

接下来,你的代码

let locationXIB = locationXIBController()

...错了。这会创建一个全新的 locationXIBController 类实例,您永远不会在视图层次结构中安装它。您应该将该行设为 IBOutlet:

@IBOutlet weak var locationXIB: locationXIBController!

然后您应该控制并从 StoryBoard 中的 locationXIBController 拖动到视图控制器中的插座上。这将导致 Interface Builder 连接插座。

现在,当您运行程序时,变量 locationXIB 将在加载时连接到情节提要/XIB 中的 locationXIBController 视图。

【讨论】:

  • 感谢您的回答。但是,我无法将视图与 MapViewController 拖动并链接,因为 locationXIB.xib 是独立的 xib 文件,而不是在情节提要中。那么我将如何使用现有的设置来解决这个问题?
  • 您仍然可以将链接连接到 XIB。我已经有一段时间没有这样做了,但我似乎记得您需要使 XIB 的拥有类与您连接的视图控制器相匹配。
  • 问题是 XIB 已经有一个拥有的类,正在执行其他代码,这不能从 MapViewController 完成,我认为您不能将 XIB 文件连接到 2 个不同的类。
  • 在由MapViewController 控制的情节提要场景中,是否存在代表locationXIBController 的视图?如果是,就是您需要连接到邓肯提到的locationXIB 出口。如果不是,locationXIBController 实例如何出现在屏幕上?
  • @theMikeSwan 没有,整个过程以编程方式完成
【解决方案2】:

除了@Duncan C 的回答,你可以检查MapViewController 类的viewDidLoad() 方法顶部是否需要super.viewDidLoad()?不这样做可能会导致您的应用出现古怪问题。

【讨论】:

    【解决方案3】:

    我问:

    那么 detailViewWillShowUpDelegate 是否真的指向任何东西,或者它是 nil 吗?

    你回答:

    我刚刚尝试调试,实际上是 nil

    这就是问题所在……您需要将detailViewWillShowUpDelegate 设置为指向一个有效的委托对象。这通常在 .xib 文件或情节提要中完成,有时人们会忘记建立这种联系,因此请检查是否有意义。否则,您只需要在某个时间点获得对委托的引用,然后相关代码就可以运行和设置。

    【讨论】:

    • 感谢Caleb的回复,问题出在这里:XIB文件已经连接到一个类,所以我不能真正将它链接到MapViewController,我尝试用locationXIB = UINib(nibName: "locationXIB", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! LocationXIBView实例化它没有结果.关于如何实例化/连接到 LocationXIBController 的现有实例,我已经没有想法了
    • 看看你是如何为 owner 参数传递 nil 的?如果您这样做,.xib 中连接到文件所有者的任何连接都将为零。您确实必须在 .xib 中设置 File's Owner 的 class,但这只是让 Xcode 知道什么可以连接到 File's Owner 代理...您仍然需要传入一个实际的对象加载 .xib 时的那种类型。而且由于文件的所有者通常是充当某些视图的委托的视图控制器,因此如果这是您问题的根源,我不会感到惊讶。
    • .xib 连接到LocationXIBContoller 类(这个类是所有者),而不是MapViewController,但是代理需要设置为MapViewController,但是文件不能拥有 2 个所有者权利
    • 那么你需要在加载.xib中的对象后设置委托。同样,将nil 传递给文件所有者可能不是正确的做法,尤其是在您费心设置文件所有者代理的类型时。
    • 但是 .xib 确实有一个所有者,它是 LocationXIBController - 那是文件所有者。但是我需要将它与 MapViewController 链接,这是一个完全不同的类,并且这个类不是 .xib 文件的所有者。
    【解决方案4】:

    回答@Paulw11 的功劳

    我终于设法通过这样的交流使其正常工作:

    步骤 1) MKAnnotation 和 MKAnnotationView 之间通过协议进行 1:1 通信

    步骤 2) MKAnnotationView 和 MapViewController 之间通过协议进行 1:1 通信,传递相同的数据

    终于像魅力一样工作了,谢谢!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-23
      • 2019-08-31
      • 2013-09-30
      • 1970-01-01
      • 2017-05-16
      • 2020-01-16
      • 1970-01-01
      相关资源
      最近更新 更多