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")
}
}
Related
I'm trying to implement Siri Shortcuts. To handle them I have to override the restoreUserActivityState function, but when I override it into my class which inherits from UIViewController, it results into this error: "Overriding 'restoreUserActivityState' must be as available as declaration it overrides". I tried to make my class and my function public but the error persists. Any idea how can I resolve this issue?
When you override a overridden method from a superclass, you make sure that, you are setting method in the subclass with higher access level than the superclass you inherit from. You can use open keyword.
Example:
class ViewController1: UIViewController {
override func restoreUserActivityState(_ activity:NSUserActivity) {
}
}
class ViewController2: ViewController1 {
open override func restoreUserActivityState(_ activity: NSUserActivity) {
}
}
I Hope, it solves your problem.
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.
I am trying to add a default implementation to one of my delegate methods. However, after adding the default implementation and removing the method from the class that implements the protocol, I get does not conform to protocol error. It works in a playground.
protocol NavigationDelegate: NSObjectProtocol {
func didSetToolbarVisible(_ isVisible: Bool)
}
extension NavigationDelegate {
func didSetToolbarVisible(_ isVisible: Bool) {
print("Default implementation")
}
}
class MyViewController: NavigationDelegate {
// 'does not conform to protocol' error
}
What am I missing?
A class does not conform to NSObjectProtocol by default, that causes the error.
Change
protocol NavigationDelegate: NSObjectProtocol
to
protocol NavigationDelegate: class
Your NavigationDelegate uses a base protocol of NSObjectProtocol. This means that anything that conforms to NavigationDelegate must also conform to NSObjectProtocol. Change your class declaration to the following:
class MyViewController: NSObject, NavigationDelegate.
Solved it! My NavigationDelegate and its extension were in a different target than the one that MyViewController belongs to. Simply moving the extension to the same target worked.
Hope this helps someone in the future 🤞
In Xcode 8 I'm trying to make a subclass of UICollectionViewController and UICollectionViewLayout but I get the error:
Multiple inheritance from classes 'UICollectionViewController' and 'UICollectionViewLayout'
but they have different parents classes. I'm trying to follow http://nshint.io/blog/2015/07/16/uicollectionviews-now-have-easy-reordering/ tutorial for reorder custom size cells
class WordCollectionViewController: UICollectionViewController, UICollectionViewLayout {
// ...
override func invalidationContext(forInteractivelyMovingItems targetIndexPaths: [IndexPath], withTargetPosition targetPosition: CGPoint, previousIndexPaths: [IndexPath], previousPosition: CGPoint) -> UICollectionViewLayoutInvalidationContext {
var context = super.invalidationContext(forInteractivelyMovingItems: targetIndexPaths, withTargetPosition: targetPosition, previousIndexPaths: previousIndexPaths, previousPosition: previousPosition)
return context
}
}
Beyond my comment. Swift DOES NOT support multiple inheritances. UICollectionViewLayout is a class, so since your WorldCollectionViewController is already inheriting from UICollectionViewController you cannot inherit from UICollectionViewLayout (you also don't want to). This:
class ViewController: UIViewController, UITextFieldDelegate {
}
is not multiple inheritances but a single inheritance from the UIViewController and conformance to a protocol UITextFieldDelegate.
You can read more about what protocols are and how to use them here: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html
Essentially protocols are like a set of guidelines. These guidelines specify methods and properties. If a class conforms to a protocol then it must implement the methods and properties described in the protocol's guidelines. For example:
protocol hasAVariablePotato {
var potato: String! { get set }
}
Any object that conforms to this protocol must have a variable (not a let constant) potato that is of type String and implicitly unwrapped. Like so:
class PotatoFarmer: Farmer, hasAVariablePotato {
}
The above PotatoFarmer class inherits from a Farmer class and but does not conform to hasAVariablePotato because there is no potato var! So the above will generate the error:
Type 'PotatoFarmer' does not conform to protocol 'hasAVariablePotato'
To fix this error the programmer must add in the properties and methods of the protocol, like so:
class PotatoFarmer: Farmer, hasAVariablePotato {
var potato: String!
}
The error will now disappear because you have conformed to the protocol.
For your situation you want to make separate subclasses of UICollectionViewLayout and UICollectionViewLayoutAttributes. To see how to do this check here (a great FREE tutorial on the subject):
https://www.raywenderlich.com/107439/uicollectionview-custom-layout-tutorial-pinterest
Swift doesn't support multiple inheritances. UICollectionViewController and UICollectionViewLayout both are class. Don't inherit both the class. You can use below code instead
import Foundation
import UIKit
class Test:UICollectionViewLayout{
override func invalidationContext(forInteractivelyMovingItems targetIndexPaths: [IndexPath], withTargetPosition targetPosition: CGPoint, previousIndexPaths: [IndexPath], previousPosition: CGPoint) -> UICollectionViewLayoutInvalidationContext {
var context = super.invalidationContext(forInteractivelyMovingItems: targetIndexPaths, withTargetPosition: targetPosition, previousIndexPaths: previousIndexPaths, previousPosition: previousPosition)
return context
}
}
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.