子类中的委托方法有时不使用Swift 5编译器调用

子类中的委托方法有时不使用Swift 5编译器调用,swift,xcode,swift5,Swift,Xcode,Swift5,编辑:如前所述,这已被修复,将与下一个Xcode/Swift版本一起发布 在使用Swift 4和Swift 5代码基将Xcode 10.1更新为Xcode 10.2之后,我看到了很多奇怪的行为 问题之一是在一个ViewController上不再调用ScrollView委托方法。简化的视图层次结构如下所示: | ScrollView (ParentScrollView) | -- Stack View | ---- ScrollView (ChildScrollView) | ---- Scro

编辑:如前所述,这已被修复,将与下一个Xcode/Swift版本一起发布


在使用Swift 4和Swift 5代码基将Xcode 10.1更新为Xcode 10.2之后,我看到了很多奇怪的行为

问题之一是在一个ViewController上不再调用ScrollView委托方法。简化的视图层次结构如下所示:

| ScrollView (ParentScrollView)
| -- Stack View
| ---- ScrollView (ChildScrollView)
| ---- ScrollView (ChildScrollView)
| ---- ScrollView (ChildScrollView)
它充当具有多个页面的视图:
ParentScrollView
可以水平滚动,而
ChildScrollView
s可以垂直滚动

ViewController是所有ScrollView(在故事板中设置)的委托,但在滚动任何视图(ParentScrollView或ChildScrollView)时,都不会调用委托方法(如
ScrollViewDiEndDecreating
)。
ViewController
基类符合
UIScrollViewDelegate

我尝试过在代码中设置委托,除此之外,我不知道我可能做错了什么。转换并没有改变类中的任何代码,但在更新之前一切都运行良好。我也找不到对手势、代理或滚动视图的任何更改

这似乎是Swift 5编译器的一个bug。此外,有时它可以工作,有时它不能-所有这些都不需要更改任何代码或项目设置


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

由于所有的
UIScrollViewDelegate
方法都是可选的,如果编译器认为您没有实现它们,您将永远不会看到错误,最有可能发生的是苹果在Swift 5中更改了方法签名(再次)由于某种原因,迁移工具无法工作。
检查方法名称以及更新到USwift 5文档的
UIScrollViewDelegate
,您将看到可能您的方法名称不同,只需更正它们,所有操作都应重新运行。

编辑:,如前所述,这已被修复,将与下一个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!
    }
}
编译器似乎认为,如果基类没有实现委托方法,那么委托方法就没有实现。如果只有子类实现它,它就找不到它


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

我们与UITextViewDelegate一起遇到了这个问题


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

看起来这个问题早在2016年就存在了,并且在某一点上得到了修复:

正如Jan指出的,这是一个快速的5回归。斯威夫特和雷达都能追踪到这一点(rdar://problem/49482328). 这也已经修复了(),但我们需要等待下一个Xcode/Swift版本


编辑:从Xcode 10.3开始,我们观察到该漏洞已修复,但我们仍在监控它是否已永久修复。

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

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

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

对于那些已经升级到Xcode 10.3的用户来说,这个构建设置选项似乎不再可见,但是您仍然可以通过项目的pbxproj文件直接对其进行更改,之后它应该会出现在Xcode UI中。
SWIFT\u编译模式=singlefile


Unrelated:应该有一种更好的方法来完成您正在尝试的操作,而不是嵌套滚动视图。@RakeshaShastri Hm,可能作为子视图控制器?可能。我不知道,因为我不知道它们是干什么用的。反对票可能是因为你没有表明问题太模糊。我没有投否决票。这根本不应该被否决!这是最新Xcode/Swift的突破性变化compiler@JanSchlorf请您更新您的编辑,使用Xcode和Swift的确切版本修复问题,而不仅仅是说“下一个Xcode/Swift版本”?谢谢您的回答。命名是正确的,但我投了更高的票,因为它可能对未来的读者有用。这个答案可能有用,但正确的答案是添加@objc。方法签名正确。我可以确认这就是问题所在。它在我们的应用程序中造成了很多错误,我们昨天也升级了。这个Swift 5编译器错误可能适用于所有未在相关基类中实现的委托方法。更糟糕的是,这个bug有时只在发布版本中出现。@ClausJørgensen您现在找到解决方案了吗?我现在正在使用以前版本的Xcode进行构建,因为试图在我们的项目中找到所有可能的错误案例太冒险了。@JanSchlorf您的解决方案工作得很好。如果你想一想Objective-C选择器是如何工作的,那么这个错误可能会发生是有道理的!尽管我所有的相关代码都是用swift编写的,但这对我来说还是有效的。我认为它之所以有效,是因为它引入了动态查找/动态调度。我花了一些时间进入其中,创建一个帐户,然后重新打开它。给它一些投票,这样它就会引起注意。这是一个非常严重的问题,在一个生产准备好的编译器。提到的公关说,它将发布的Swift 5.1,它应该与Xcode 11(测试版),而不是10.3。