Joey
Joey

Reputation: 2968

type casting when creating an instance from a parent class

I would like to ask something about type-casting in Swift.

There are 2 classes.

  1. RootViewController
  2. MyViewController

and the class hierarchy is like below:

class RootViewController: UIViewController {

}

class MyViewController: RootViewController {

}

and, I want to simply call instance function to create an instance from xib file. so I implemented below function in RootViewController.

Objective-C

+ (instancetype)instance {
    return [[[self class] alloc] initWithNibName:NSStringFromClass([self class]) bundle:nil];
}

Swift

public class func instance<T:RootViewController>() -> T {
    let type = self as UIViewController.Type
    let name = NSStringFromClass(type).components(separatedBy: ".").last!
    let instance = type.init(nibName: name, bundle: nil)
    return instance as! T
}

and, usage is like below.

Objective-C

MyViewController *vc = [MyViewController instance];

Swift

let vc = MyViewController.instance() as! MyViewController

Question:

Do I have to always cast the type of instance using as! MyViewController in Swift? Or can anybody advise me a better approach in Swift?

Any help would be appreciated!

Upvotes: 2

Views: 266

Answers (3)

Orkhan Alikhanov
Orkhan Alikhanov

Reputation: 10050

class RootViewController: UIViewController {
    public class func instance() -> Self {
        func inner<T: RootViewController>(type: T.Type) -> T {
            let name = NSStringFromClass(type).components(separatedBy: ".").last!
            let type1 = type as UIViewController.Type
            let instance = type1.init(nibName: name, bundle: nil)
            return instance as! T
        }
        return inner(type: self)
    }
}

I would suggest creating an extension method:

extension UIViewController {
    public class func instance() -> Self {
        func inner<T: UIViewController>(type: T.Type) -> T {
            let name = NSStringFromClass(type).components(separatedBy: ".").last!
            return T(nibName: name, bundle: nil)
        }
        return inner(type: self)
    }
}

Upvotes: 2

nayem
nayem

Reputation: 7585

Okay you can instantiate in these three ways:

  1. Swift inference to Type:

    let myVC = RootViewController.instance()   //Swift will automatically infer the type
    
  2. Explicitly telling the Type:

    let myVC: RootViewController = RootViewController.instance()
    
  3. Casting to your Type:

    let myVC = RootViewController.instance() as! RootViewController
    

All these three are valid.

Upvotes: 0

hardikdevios
hardikdevios

Reputation: 1789

You can Also use like this way

let vc:MyViewController = MyViewController.instance()

Upvotes: 3

Related Questions