return new ViewController in Swift - swift

this is a follow up question to this : Assign ViewController to Class or vice versa
So i have a ViewController called SwipeStepViewController, it subclasses from ORKActiveStepViewController. In the SwipeStep class i try to override the default ViewController with my custom SwipeStepViewController.
I tried to override the +stepViewControllerClass
method and return my Custom Viewcontroller inside the SwipeStep class:
import ResearchKit
class SwipeStep:ORKActiveStep{
override func stepViewControllerClass(){
return SwipeStepViewController.self
}
}
but this does not work at all.
I use researchkit, but i guess it is a general swift question.

I don't have any experience with ResearchKit, but after taking a look at the Objective-C code I believe your method should be:
override class func stepViewControllerClass() -> AnyClass {
return SwipeStepViewController.self
}
To explain why you're getting the errors:
Method does not override any method from its superclass.
and
'SwipeStepViewController.Type' is not convertible to '()'
take a look at the class method (indicated by the +) you're supposedly overriding:
+ (Class)stepViewControllerClass {
return [ORKFormStepViewController class];
}
Compare this with your method:
override func stepViewControllerClass(){
return SwipeStepViewController.self
}
which is neither a class method, nor returns a class and it's clear where the errors are coming from.

Quite late to the party, but I believe your function should be as follows:
class SwipeStep : ORKActiveStep {
static func stepViewControllerClass() -> SwipeStepViewController.Type {
return SwipeStepViewController.self
}
}

That function should return a Class. Take a look at the section in the Swift reference on Metatype Types:
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Types.html
Your function should be
override func stepViewControllerClass(){
return SwipeStepViewController.self
}

Related

How to class the superclass of a superclass in Swift?

ArtistVC is a subclass of CategoryVC which is a subclass of BrowserVC.
Most of ArtistVC's UITableView Data Source methods wind up calling CategoryVC's implementation of those methods with return super.tableView(tableView, cellForRowAt: adjustedIndexPath)(for example), after some other things happen of course, like modifying the indexPath passed to the method.
But sometimes I actually want to bypass CategoryVC's implementation and use BrowserVC's implementation.
super.super.someMethod() apparently isn't the answer. Is this possible?
There's a (convoluted) way to do this but it requires that the intermediate class "contributes" to the bypassing of its override.
For example:
class A
{
func doIt(_ parameter:Int) { print("A.doIt(\(parameter))") }
}
class B:A
{
override func doIt(_ parameter:Int) { print("B.doIt(\(parameter))") }
var super_doIt:(Int)->() { return super.doIt }
}
class C:B
{
override func doIt(_ parameter:Int)
{ super.super_doIt(parameter) }
}
let c = C()
c.doIt(3) // A.doIt(3)

Override Objective-C Methods in Swift File

I have some methods in Objective-C.
I created a subclass from Objective-C superclass.
Now I want to override the Objective-C superclass method in my Swift class.
My code:
#objc class JobBusinessTableViewCell: AdItemTableViewCell {
override func commonInit() {
super.commonInit()
}
override func updateWithAd(ads: ResponseSimpleAd) {
super.updateWithAd(ads)
}
}
Here AdItemTableViewCell is an Objective-C superclass.
I want to override updateWithAd method in Swift.
How can I do this?
I found the answer .. But looks weird ..
Worked Code :
public final override func update(with ad : ResponseSimpleAd) {
super.update(with: ad)
}
I don't understand the method name change in swift .. But working as expected ...

Argument of `#selector` does not refer to an initializer or method

I'm trying to perform a protocol extension method in the background:
performSelectorInBackground(#selector(retrieveCategories()), withObject: nil)
However I get the below error message:
Argument of `#selector` does not refer to an initializer or method
Here is my protocol declaration:
#objc protocol DataRetrievalOperations {
optional func retrieveCategories()
...
}
And my extension:
extension DataRetrievalOperations {
func retrieveCategories() {
...
}
}
How can I achieve this?
Try this:
#selector(DataRetrievalOperations.retrieveCategories)
With omitting class (or protocol) name in #selector(...) notation, Swift assumes the enclosing class, which may be a ViewController, I guess.
One more issue:
It seems Swift cannot implement #objc protocol methods with default implementation in protocol extension.
(I think I have heard something about this, but I couldn't find any articles for now.)
You may need to implement it in your own class's extension or find another way.
extension CategoriesViewController {
func retrieveCategories() {
//...
}
}
I need to add that this will solve the first issue and #selector(retrieveCategories) will work.
You can't add an #Objc method in a Protocol Extension. You need to extend the Class which inherits NSObject and that Protocol and add the objc function there like so:
#objc protocol DataRetrievalOperations {
optional func retrieveCategories()
}
class aClass: NSObject, DataRetrievalOperations {
func method() {
performSelectorInBackground(#selector(retrieveCategories), withObject: nil)
}
}
extension aClass {
#objc func retrieveCategories(){
}
}
This will work.

Swift: overriding typealias inside subclass

So I was thinking about a custom pattern in my project, but I can't get it to work. The main idea is to change the typealias on every subclass to get access to the subclass specific interface.
protocol InstanceInterface: class {
typealias Interface
var interface: Interface { get }
}
// Baseclass
protocol FirstClassInterface: class { /* nothing here for the example */ }
class FirstClass: InstanceInterface, FirstClassInterface {
typealias Interface = FirstClassInterface
var interface: Interface { return self }
}
// Subclass
protocol SecondClassInterface: FirstClassInterface {
func foo()
}
class SecondClass: FirstClass, SecondClassInterface {
typealias Interface = SecondClassInterface // <--- This does nothing :(
func foo() { print("hello world") } // Swift 2.0 here
}
// Lets say I want to call foo trough the interface
let test = SecondClass()
test.interface.foo() // 'Interface' does not have a member named 'foo'
Is there something I'm doing wrong or do I misunderstand some Swift concepts here?! I do need to subclass here to not to implement everything from super class' protocols over and over again. Is my little pattern even possible? I'd appreciate any help. :)
Would something like this work for your purposes?
class MyClass<T> {
}
class MySubclass1: MyClass<String> {
}
class MySubclass2: MyClass<Int> {
}
Unfortunately there is no good workaround for this problem.
The main idea to override the typealias would work in this case but consider the following:
protocol TakeAndGet {
typealias T
func take(value: T)
func get() -> T
}
class FirstClass: TakeAndGet {
typealias T = FirstClass
var property = 0
func take(value: T) {
value.property = 4
}
func get() -> T {
return FirstClass()
}
}
class SecondClass: FirstClass {
typealias T = SecondClass
var property2 = "hello"
}
If the typealias of the SecondClass overrides the other one the take method would work since it takes a subclass which can be treated as the superclass. But the get method cannot implicitly convert FirstClass to SecondClass. Therefore it is not possible to override a typealias.
Now if we want to override the get function with get() -> SecondClass it wouldn't work since it has not the same signature as the one in the superclass. In addition we inherit the get method which results in an ambiguous use:
SecondClass().get() // which type gets returned? SecondClass or FirstClass
So you have to try a different approach.

How to tell if a subclass overrides a method in Swift

I’ve got a Swift class Parent that has a method doSomething() and I want to detect (in Parent) if a subclass has overridden doSomething(). How do I do that?
class Parent {
func doSomething() {}
func subclassOverridesDoSomething() -> Bool {
// what goes here?
return true
}
}
class Child: Parent {
override func doSomething() {}
}
I know I can do this with NSObject or even the Objective C runtime functions, but how can I do it with Swift classes?
You can use the Objective-C runtime provided you expose the function with dynamic:
class Parent {
func doSomething() {}
func subclassOverridesDoSomething(t:Parent.Type) -> Bool {
let originalMethod = class_getInstanceMethod(t, "doSomething")
return originalMethod != nil
}
}
class Child: Parent {
dynamic override func doSomething() {}
}
Parent().subclassOverridesDoSomething(Child.self)
If you omit dynamic, it won't work because Objective-C can't see the method.
Well Swift doesn't really offer methods to do that.
Also in my opinion, there is no disadvantage in using Objective-c methods like method_getImplementation or the NSObject. You will have to use the methods objective-c offers you to solve your problem.
For example:
let selector = Selector("viewWillAppear:")
let originalMethod = class_getInstanceMethod(YourClass, selector)