This question already has answers here:
Swift 3 protocol extension using selector error
(7 answers)
Closed 5 years ago.
I tried to make a default implementation of protocol UIScrollViewDelegate, for example:
extension UIScrollViewDelegate {
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
//...
}
}
But In a subclass UITableViewController (which conforms to UIScrollViewDelegate and) does not contain any implementation this method (neither in base class nor in subclass), this extension-provided implementation won't be called
Is there any solution to provide a default implementation for these methods?
Just create an extension of UIScrollView to conform to UIScrollViewDelegate protocol like this:
extension UIScrollView: UIScrollViewDelegate {
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
// ...
}
}
You are trying to make a Swift protocol extension on an Objective-C protocol. That's never going to work, because Objective-C cannot see a Swift protocol extension, so Cocoa (which is Objective-C) will never know about your implementation and will never call it.
Related
I have a superclass in a framework that implements an Objective-C protocol with optional methods. The superclass does not implement these optional methods. In the project that uses this framework, I would like to implement these methods in my subclass. However, I'm getting errors from Swift. Is there a better way to do this or a better design in the framework?
Note: Please keep in mind that the SuperClass is in an XCFramework and the SubClass was inside the application where the created XCFramework was imported.
import UIKit
class SuperClass: NSObject, UIScrollViewDelegate {} // This will be inside an XCFramework
class SubClass: SuperClass {
override func scrollViewDidScroll(_ scrollView: UIScrollView) { // Error: Method does not override any method from its superclass
print("test")
}
}
I have a protocol which declaration looks like this:
protocol RefreshableView where Self: UIView {
func reload()
}
And it has default implementation which looks as follows:
extension RefreshableView {
func reload() {
print("Default implementation")
}
}
Then if I declare another (empty) extension of UIView conforming to this protocol I get compile-time error stating that UIView does not conform to the protocol.
extension UIView: RefreshableView {}
It should not be a case from my point of view, as default implementation is provided. However if I remove where statement (restriction to the classes which can conform to the protocol) from declaration of the protocol, everything works as expected. Another option to silence this error is to give the same where statement next to default extension declaration, but it feels redundant as I already let compiler know the protocol is supposed for narrow audience. Is there an explanation to this behavior?
What you're saying is that this doesn't compile:
protocol RefreshableView where Self: UIView {
func reload()
}
extension RefreshableView {
func reload() {
print("Default implementation")
}
}
extension UIView: RefreshableView {
}
As Rob Napier points out in a comment, that's a very odd thing to say, because if UIView itself is going to adopt RefreshableView, then what's the protocol for? The original declaration of the protocol means that only a UIView subclass can adopt RefreshableView, so what the compiler expects is that that's what will happen:
protocol RefreshableView where Self: UIView {
func reload()
}
extension RefreshableView {
func reload() {
print("Default implementation")
}
}
class MyView: UIView {}
extension MyView: RefreshableView {
}
That is a useful real-world case, and it compiles just fine.
So you could file a bug against your original code, but you have to admit it
is a very peculiar edge case to start with; you are saying something that no one would in fact ever say.
I have a UIViewController only protocol
protocol VCProtocol where Self: UIViewController {}
I have a function with VCProtocol parameter. Inside the function I can not access any property of UIViewController
func testFunction(vcProtocol: VCProtocol) {
// vcProtocol.view ‼️ error: Value of type 'VCProtocol' has no member 'view'
}
Though I can cast the protocol parameter to UIViewController and then access the property like this:
func testFunction(vcProtocol: VCProtocol) {
(vcProtocol as! UIViewController).view
}
Is this is the way? Do we have any better way?
You can use the & operator to combine protocols
protocol VCProtocol where Self: UIViewController {}
func testFunction(vcProtocol: VCProtocol & UIViewController) {
let view = vcProtocol.view
}
It seems like this is now supported properly from Swift 5. You can try it Xcode 10.2 beta 4. For older versions, you would have to resort to #Ricky Mo's solution.
protocol VCProtocol: UIViewController {
func testFunction(vcProtocol: VCProtocol)
}
class A: UIViewController, VCProtocol {
func testFunction(vcProtocol: VCProtocol) {
debugPrint(vcProtocol.view)
}
}
From the notes,
Protocols can now constrain their conforming types to those that
subclass a given class. Two equivalent forms are supported:
protocol MyView: UIView { /*...*/ }
protocol MyView where Self: UIView { /*...*/ }
Swift 4.2 accepted the second form, but it wasn’t fully implemented
and could sometimes crash at compile time or runtime. (SR-5581)
(38077232)
I am trying to implement the CVCalendar cocoapod (https://github.com/Mozharovsky/CVCalendar) and in the instructions it says:
'CVCalendar requires an implementation of two protocols CVCalendarViewDelegate and CVCalendarMenuViewDelegate, please implement both.'
I dont understand how to go about doing this.
You just need to make your class a subclass of CVCalendarViewDelegate and CVCalendarMenuViewDelegate.
class ViewController: UIViewController, CVCalendarViewDelegate, CVCalendarMenuViewDelegate {
Documentation: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Inheritance.html#//apple_ref/doc/uid/TP40014097-CH17-ID195
Take a look at the answer to this question: Conform to protocol in ViewController, in Swift
As per Oliver's answer you need to add protocols to your class declaration :
class ViewController: UIViewController,CVCalendarMenuViewDelegate,CVCalendarViewDelegate {
You also need to add these two functions to comply with the new protocols:
func presentationMode() -> CalendarMode{
return .monthView
}
func firstWeekday() -> Weekday{
return .monday
}
Can I use protocol extensions for UIScrollViewDelegate to offer a default implementation of scrollViewDidScroll to all my views that conforms to this protocol?
Because I want to be able to in a single file propagate the same scrollViewDidScroll implementations through all my other views, without having to implement this method in each view, which are 6.
What worked for me was to implement the extension on the type implementing the protocol, i.e. UIViewController
extension UIViewController{
func scrollViewDidScroll(scrollView: UIScrollView){
//do something
print("scrolled\n")
}
}
In Swift 2.0 only: It seems like you should be able to do something like below but it doesn't seem to work:
extension UIScrollViewDelegate{
func scrollViewDidScroll(scrollView: UIScrollView){
//do something
}
}
Any implementation of scrollViewDidScroll you write in a type that conforms to this protocol I believe should overwrite this implementation.