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?
Creating Optional Delegate Methods In Swift, using the @objc modifier a protocol can be marked as an Objective-C protocol. After marking the protocol as @objc , specific protocol functions can be marked with @objc which allows the optional modifier to be used on the marked function.
Delegates are a design pattern that allows one object to send messages to another object when a specific event happens. Imagine an object A calls an object B to perform an action.
A new SwiftUI project doesn't have an app or scene delegate by default. Since iOS 14, you create scenes in the App structure. SwiftUI has some built-in scene types like WindowGroup or DocumentGroup .
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?
We ran into this with a UITextViewDelegate
Another workaround is to add the @objc
tag to the method in the superclass
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With