How to override a oc category method in .swift - ios

I have a OC UIViewController category , which decleared a class method of UIViewController
+(BOOL)hasStoryBoard;
And I also import this category into xxx-Bridging-Header.h file
My swift class CustomVC is inherited UIViewController. I want override +(BOOL)hasStoryBoard to give a BOOL-type value.This method will called in other class to determine CustomVC's new instance's some feature.
But in my CustomVC.swift I cannot find method like this:
override class func hasStoryBoard()->bool{}
I must override this method to give a YES,or give it's subclass a NO,so on...
I searched this site and find this Swift: How to call a category or class method from Objective-C. In this discussion , explained and tell you how to call the method,not how to override the method .
Can you find solution to override oc category's class method? Or give a workaround in my case.
All my code is :
#interface UIViewController (StoryBoard)
+(BOOL)hasStoryBoard;
-(void)haha;
#end
.
#implementation UIViewController (StoryBoard)
static BOOL hasStoryboard = NO;//默认没有
+(BOOL)hasStoryBoard{
return hasStoryboard;
}
-(void)haha{}
#end
.
class CustomVC: UIViewController {
//this override is correct,have syntax input prompt
override func haha() {
}
//this override is incorrect ,no syntax input prompt
override func hasStoryBoard()->Bool{
return true
}
}

+(BOOL)hasStoryBoard;
defines a class method in Objective-C, but in your Swift subclass
you define an instance method:
override func hasStoryBoard()->Bool{
return true
}
That must be a class method as well:
override class func hasStoryBoard()->Bool{
return true
}
Tip: If you open the Objective-C interface (.h) file in Xcode and
select "Navigate->Jump to Generated Interface" from the Xcode menu
then you'll see excacly how the Objective-C interface is imported to
Swift. In your case:
extension UIViewController {
open class func hasStoryBoard() -> Bool
open func haha()
}
Now you can copy the function definition and use it to define
the overriding method in your subclass.

Related

Can't pass a reference to a protocol where self is specified

I have a project using the NVActivityIndicatorView library and I am trying to extract some logic from two view controllers. Both view controllers conform to NVActivityIndicatorViewable whose definition is:
// From the libaray. I don't want to modify this.
public protocol NVActivityIndicatorViewable {}
public extension NVActivityIndicatorViewable where Self: UIViewController
{
func startAnimating( ... ) { ... }
func stopAnimating() { ... }
}
And as a result, I expected to be able to pass one of these view controllers in and use the startAnimation and stopAnimation methods on it.
func sharedLogic(sender: NVActivityIndicatorViewable)
{
sender.startAnimating( ... )
sender.stopAnimating()
}
However, this fails with the compiler error 'NVActivityIndicatorViewable' requires that 'NVActivityIndicatorViewable' inherit from 'UIViewController'
Trying this with sender: UIViewController, this fails with the compile time error Value of 'UIViewController' has no member 'startAnimating' as I expected.
func sharedLogic(sender: UIViewController)
{
sender.startAnimating( ... )
sender.stopAnimating()
}
I have found two potential solutions:
Create an empty subclass that specifies both these types: (This new type doesn't contain any logic)
class ActivityIndicatorViewController: UIViewController, NVActivityIndicatorViewable { }
Use an extension to specify all view controllers can be activity indicators: (This causes redundant conformance errors on many classes)
extension UIViewController: NVActivityIndicatorViewable { }
Can I accomplish this without creating a new type?
Environment settings:
Xcode version: 10.1
iOS Deployment Target: 9.0
Swift version: 3
What you want here is a composition type - a type that both inherits from UIViewController and conforms to NVActivityIndicatorViewable:
UIViewController & NVActivityIndicatorViewable
You can use this directly as the parameter type for your method:
func sharedLogic(sender: UIViewController & NVActivityIndicatorViewable)
Or you can create a typealias for it (though I can't think of a shorter name):
typealias SomeShorterName = UIViewController & NVActivityIndicatorViewable
And then you can use SomeShorterName as the parameter type.
You set constraint on the protocol and extended the constrained one. So if you want those two functions, you need a UIViewContoller conformed to your protocol.
Move functions to the original protocol to get what you need.
public protocol NVActivityIndicatorViewable {
func startAnimating( ... )
func stopAnimating()
}
Update due to comment:
If you want to leave the original Protocol untouched, use composition type for the function:
func sharedLogic(sender: UIViewController & NVActivityIndicatorViewable) {
sender.startAnimating()
sender.stopAnimating()
}

Use generic extended swift class in Objective-c

In my project i have many swift classes that extend generic classes. And Now i'm in a need to send data from objective-c class to these swift classes. Is there any possible way to do this ?
I have tried using #objc before class as shown below
but it didn't allow me to do this.
I followed this answer stack link. But i checked when i run my app with this code it dint create the variable in the Project-swift class as shown in below image
as the variable is not created here so it gives error while calling the variable in objective-c class.
Kindly help out with better solution.
I got my solution by creating another class which contain a protocol and i indirectly call the generic extended class.
class EntityDataTable :BaseData<EntitySw> {
}
this is the generic extended class
and the another class i made to indirectly access this class in objective-c is
#objc class EntityService : NSObject {
var entityProtocol:EntityDataProtocol?
override init() {
super.init()
entityProtocol = returnDataObject()
}
func returnDataObject() -> EntityDataTable {
return EntityDataTable()
}
}
#objc protocol EntityDataProtocol{
func addFromService(source: CWEntity)
func getAll() -> [EntitySw]
}
Then i imported the Project-swift.h file in objective c class and made the object of swift class

Override function

I am taking a iOS course online provided by a famous university. I don't understand why the following code use override and it is legal.
According to the official definition, we use override to override superclass' methods. Where is the subclass and superclass in the following code?
What's been override and by what?
public override var description: String {
return "\(url.absoluteString) (aspect ratio = \(aspectRatio))"
}
Here is an example:
Your original class:
class Person {
func walk() {
//do something
}
}
Your subclass:
class Runner: Person {
override func walk() {
//do something that is different from Person's walk
}
}
In the Runner class, there is an override with the function walk. That is because it is a subclass of Person, and it can override Person's walk function. So If you instantiate a Runner:
var usainBolt = Runner()
And you call the walk function:
usainBolt.walk()
Then that will call the overriden function that you wrote in the Runner class. If you don't override it, it will call the walk function that you wrote in Person.
According to the official definition, we use override to override superclass' methods.
That's correct. The superclass in your example is the class that encloses the override of description property. This could be NSObject, some other class derived from it (directly or indirectly), or some class unrelated to NSObject that has var description: String property.
description is a property that Swift classes commonly have as a way to present themselves as a string, because description provides conformance to CustomStringConvertible protocol. This is similar to toString() method of Java, and to str() method of Python.
What's been override and by what?
The implementation of the property is what's being overridden. The class that has the implementation does the overriding.

swift 2.1, xcode 7.2. simple NEWBIE about why it works in Playground but not in application

This code works in Playground, but I get a compile error when I define this in my project in Xcode 7.2
Here is my Playground screenshot
https://goo.gl/yJ4Q75
Error is: method does not override any method in the super class
public class A {
private func myUnavailableMethod() {
print("A. private func myUnavailableMethod()")
}
}
public class B : A {
override func myUnavailableMethod() {
print("B. func myUnavailableMethod()")
}
}
Motivation to this Playground was an error when trying to override a method, compiler was complaining as "Not available"
class MySFSafariViewController: SFSafariViewController {
override init() {
}
}
---- FOUND HOW THEY MARKED a method as unavailable.
When jumping to the Objective C declaration.
#interface SFSafariViewController : UIViewController
/*! #abstract The view controller's delegate */
#property (nonatomic, weak, nullable) id<SFSafariViewControllerDelegate> delegate;
****- (instancetype)init NS_UNAVAILABLE;****
The meaning of private/internal/public is different in Swift compared to some other languages.
IF and it is an IF you have your classes as two separate files in the project, then it's pretty clear.
private - scope is visibility is the file that holds the code
internal - scope of visibility is the namespace
public - scope of visibility is full access from anywhere
In Xcode Playground their are both in one file so the method is visible to class B.
The myUnavailableMethod of class A is private, therefore it can't be overridden. Change the method declaration to be internal by removing the private keyword.

Override Objective-C class method in Swift

I'm trying to use JSONModel in a Swift project.
I would like to override the method keyMapper from JSONModel but I don't find how to override an Objective-C class method in the model class.
The signature of the method is:
+(JSONKeyMapper*)keyMapper;
How can I do that?
You do it just like you override an instance method, except with the class keyword:
override class func keyMapper() -> JSONKeyMapper! {
//code here
}

Resources