子 class 中的委托方法有时不会被 Swift 5 编译器调用

Delegate methods in child class sometimes not called with Swift 5 compiler

编辑: 作为 sunshinejr pointed out ,这已得到修复,将与下一个 Xcode/Swift 版本一起发布。


在将 Xcode 10.1 更新到 Xcode 10.2 后,我看到了很多奇怪的行为,包括 Swift 4 和 Swift 5 代码库。

其中一个问题是 ViewController 不再调用 ScrollView 委托方法。简化视图层级如下:

| ScrollView (ParentScrollView)
| -- Stack View
| ---- ScrollView (ChildScrollView)
| ---- ScrollView (ChildScrollView)
| ---- ScrollView (ChildScrollView)

它作为具有多个页面的视图:ParentScrollView 可以水平滚动,ChildScrollView 可以垂直滚动。

ViewController 是所有 Scrollviews 的委托(在 Storyboard 中设置),但是在滚动任何视图(ParentScrollView 或 ChildScrollView)时不会调用委托方法(如 scrollViewDidEndDecelerating)。 ViewController基础class符合UIScrollViewDelegate.

我试过在代码中设置委托,除此之外我不知道我可能做错了什么。转换没有更改 class 中的任何代码,但在更新之前一切正常。我在 Swift 5 Release Notes.

中也找不到一般的手势、委托或滚动视图的任何更改

这似乎是 Swift 5 编译器的错误。此外,它有时有效,有时无效 - 所有这些都无需更改任何代码或项目设置。

为什么这不再有效?有没有其他人经历过类似的行为?

由于所有 UIScrollViewDelegate 方法都是可选的,如果编译器认为您没有实现它们,您将永远不会看到编译器的错误,很可能发生的事情是 Apple 在 [=15] 中更改了方法签名=] 5(再次)并且由于某种原因迁移工具没有工作。
检查方法名称以及 UIScrollViewDelegate 更新到 USwift 5 文档,您会发现您的方法名称可能不同,只需更正它们,一切都应该再次工作。

编辑: 作为 sunshinejr pointed out ,这已得到修复,将与下一个 Xcode/Swift 版本一起发布。


我发现了问题,下面是重现问题的方法。

class A: UIViewController, UIScrollViewDelegate {
    // ...does not implement 'scrollViewDidEndDecelerating'
}

class B: A {
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        // Will not be called!
    }
}

什么有效:

class A: UIViewController, UIScrollViewDelegate {
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        // Probably empty
    }
}

class B: A {
    override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        // Will be called!
    }
}

如果基 class 没有实现委托方法,编译器似乎认为它没有实现。如果只有子class实现,它是找不到的。

我仍然无法解释为什么 Swift 5 会改变这种行为,但至少我找到了解决方案。也许有人可以提供进一步的见解?

我们 运行 使用 UITextViewDelegate

另一种解决方法是将 @objc 标记添加到超类中的方法

看起来这个问题在 2016 年也存在,并且在某一时刻得到了修复:https://bugs.swift.org/browse/SR-2919

正如 Jan 所指出的,这是一个 Swift 5 回归。 Swift 的 JIRA as well as on radar (rdar://problem/49482328). This is also already fixed (PR here) 对此进行了跟踪,但我们需要等待下一个 Xcode/Swift 版本。

编辑: 从 Xcode 10.3 开始,我们观察到错误已修复,但我们仍在监视它是否已永久修复。

升级到 Xcode 10.2 后,我仅在发布方案中遇到了同样的问题。我还测试了 Xcode 10.3,它的行为完全相同。

对于那些不想在委托实现中到处添加 @objc 的人。

快速解决方案是在构建设置中禁用 Swift 5 编译器优化:

对于已经升级到 Xcode 10.3 的人来说,这个构建设置选项似乎不再可见,但您仍然可以通过项目的 pbxproj 文件直接更改它,它应该出现在xcode UI 之后。 SWIFT_COMPILATION_MODE = singlefile;