问题
EDIT: As sunshinejr pointed out here, this has been fixed and will be released together with the next Xcode/Swift version.
I've seen a lot of weird behaviour after updating Xcode 10.1 to Xcode 10.2, both with Swift 4 and Swift 5 codebases.
One of the problems is that on one ViewController the ScrollView delegate methods are no longer called. The simplified view hierarchy is as follows:
| ScrollView (ParentScrollView)
| -- Stack View
| ---- ScrollView (ChildScrollView)
| ---- ScrollView (ChildScrollView)
| ---- ScrollView (ChildScrollView)
It acts as a view with several pages: ParentScrollView
can be scrolled horizontally, the ChildScrollView
s vertically.
The ViewController is the delegate of all Scrollviews (set in Storyboard), but the delegate methods (like scrollViewDidEndDecelerating
) are not called when scrolling any of the views (ParentScrollView or ChildScrollView). The base class of ViewController
conforms to UIScrollViewDelegate
.
I have tried setting the delegates in code, other than that I have no idea what I could be doing wrong. The conversion did not change any code in the class, but everything worked well before updating. I also couldn't find any changes to gestures, delegates or ScrollViews in general in the Swift 5 Release Notes.
This seems to be a bug with the Swift 5 compiler. Additionally, sometimes it does work, sometimes it doesn't - all without changing any code or project settings.
Why does this no longer work? Has anyone else experienced similar behaviour?
回答1:
EDIT: As sunshinejr pointed out here, this has been fixed and will be released together with the next Xcode/Swift version.
I've found the issue, here's how to reproduce it.
class A: UIViewController, UIScrollViewDelegate {
// ...does not implement 'scrollViewDidEndDecelerating'
}
class B: A {
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
// Will not be called!
}
}
What does work:
class A: UIViewController, UIScrollViewDelegate {
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
// Probably empty
}
}
class B: A {
override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
// Will be called!
}
}
The compiler seems to think that a delegate method is not implemented if the base class did not implement it. If only the child class implements it, it can't find it.
I still can't explain why this behaviour changed with Swift 5, but at least I've found a solution. Maybe someone can give further insights?
回答2:
We ran into this with a UITextViewDelegate
Another workaround is to add the @objc
tag to the method in the superclass
回答3:
Looks like this issue existed back in 2016 as well and was fixed at one point: https://bugs.swift.org/browse/SR-2919
回答4:
As Jan pointed out, this is a Swift 5 regression. This is tracked on Swift's JIRA as well as on radar (rdar://problem/49482328). This is also already fixed (PR here) but we need to wait for the next Xcode/Swift release.
Edit: As of Xcode 10.3, we observed that the bug is fixed, but we are still monitoring if it is fixed for good.
回答5:
I experienced the same issue only with the release scheme after upgrading to Xcode 10.2. I also tested Xcode 10.3 and it is exactly the same behavior.
For those who don't want to add @objc everywhere in your delegate implementation.
The quick solution is to disable the Swift 5 compiler optimisation in the build settings:
For those who already upgraded to Xcode 10.3, it seems that this build settings option is not visible anymore, but you can still change it directly via the pbxproj file of your project and it should appear in the xcode UI afterward.
SWIFT_COMPILATION_MODE = singlefile;
回答6:
Since all of UIScrollViewDelegate
methods are optionals you will never see an error from compiler if it thinks that you didn't implement them, most probably what is happening is that Apple changed method signature in Swift 5 (again) and for some reason the migration tool didn't work.
Check the methods names along with UIScrollViewDelegate
updated to USwift 5 documentation, you will see that probably your methods names are different, simply correct them and everything should work again.
来源:https://stackoverflow.com/questions/55393027/delegate-methods-in-child-class-sometimes-not-called-with-swift-5-compiler