Class casting dynamically in swift

I am trying to dyanmically cast to a class in Swift. Is this possible? Here is the code I am trying to use:

let stringClass: AnyClass = NSString.self
let anyObject: AnyObject = "foo"
let string = anyObject as! stringClass

The code fails to compile at the cast. Is this possible and if so, why is the right syntax?

  • Type 'AnyObject' does not conform to protocol 'SequenceType'
  • What's the difference between tableView.reloadData and tableView.reloadRows?
  • Convert a two byte UInt8 array to a UInt16 in Swift
  • Transparent UINavigationBar in Swift
  • How to convert video (in gallery) to NSData? in Swift
  • IOS Swift - Custom camera overlay
  • Real use case

    Here is the real issue. I am attempting to refactor this code:

    switch (value) {
        case "valueOne":
            viewController = storyboard.instantiateViewController(withIdentifier: "foo") as! FirstViewController
        case "valueTwo":
            viewController = storyboard.instantiateViewController(withIdentifier: "bar") as! SecondViewController
        default:
            return nil
    }
    

    into:

    let controllersDictionary: [String: (String, UIViewController.Type)] = [
        "valueOne" : ("bar", FirstViewController.self),
        "valueTwo" : ("foo", SecondViewController.self)
    ]
    let tuple = controllersDictionary[value]!
    let identifier = tuple.0
    let cast = tuple.1
    let viewController = storyboard.instantiateViewController(withIdentifier: identifier) as! cast
    

    4 Solutions Collect From Internet About “Class casting dynamically in swift”

    I’m not sure exactly what you’re trying to achieve, but here’s a working version of your example:

    func cast<T>(value: Any, to type: T) -> T? {
        return castedValue as? T
    }
    
    let inputValue: Any = "this is a test"
    let inputType = String.self()
    let casted = cast(value: inputValue, to: inputType)
    
    print(casted)
    

    I’m not seeing what the cast at this point is for. You can write:

    let controllersDictionary: [String: String] = [
        "valueOne" : "bar",
        "valueTwo" : "foo"
    ]
    let identifier = controllersDictionary[value]!
    let viewController = storyboard.instantiateViewController(withIdentifier: identifier)
    

    The cast does nothing for you in the code that you have shown. viewController is typed as UIViewController, but it is the correct underlying view controller subclass thanks to polymorphism; whatever the class is in the storyboard, that’s the class of this instance.

    The only time you need to cast down is when you have to message an instance with a message belonging only to the subclass, and you have not shown any such need at this point in your code.

    While there are/will be ways to make this kind of thing work, the Swifty solution (IMO) is to have your desired classes adhere to a protocol that defines the shared behavior you’re trying to use, or simply use a super class they have in common

    This allows the dynamism requried (in most cases at least) while still allowing the compile-time checks that prevent run time errors.

    For your example,

    protocol Stringable {
        func toString() -> String
    }
    
    extension String: Stringable {
        func toString() -> String {
            return self
        }
    }
    
    let thing = "foo"
    let anything: Any = thing
    let test: String? = (anything as? Stringable)?.toString()
    

    Note that this requires “Any” rather than “AnyObject” since you need to cast to a protocol

    Since you mentioned ViewControllers, I thought this might help:

    static func createViewController<T: UIViewController>(storyboard: String, scene: String) -> T? {
        return  UIStoryboard(name: storyboard, bundle: nil).instantiateViewControllerWithIdentifier(scene) as? T
    }
    

    The x as! Y.Type syntax only works when Y is explicitly stated.

    So, the compiler wants x as! NSString. The compiler crash is a bug, I suggest that you file a report.

    And just think about it for a second, how would that even help you? stringClass is of type AnyClass, and you’re force casting an AnyObject which already conforms to AnyClass. You should cast when you have a static type in mind, because casting doesn’t really make any sense otherwise.

    If you want to check, however, whether your object’s class is a subclass of a particular type, you’d use:

    x is Y.Type