Swift 4 Objective-C Runtime and casting to NSObjectProtocol

1.5k views Asked by At

In Swift 3, I had a snipped of code that called into Objective-C runtime to check if a certain class is present.

guard let managerClass = NSClassFromString("ASIdentifierManager") as? NSObjectProtocol else {
    return nil
}

This returns AnyClass instance and it is castable to NSObjectProtocol - so I could call methods like responds and perform to work with selectors.

In Swift 4, this still works at runtime, but will emit a warning:

Cast from 'AnyClass?' (aka 'Optional') to unrelated type 'NSObjectProtocol' always fails

Oddly it still works, but I am worried a certain Swift version will kill the code.

What is the proper way to get rid of this warning? To what should I cast the object, to be able to perform selectors on it dynamically?

2

There are 2 answers

7
Orkhan Alikhanov On

You should cast to NSObjectProtocol.Type:

guard let managerClass = NSClassFromString("ASIdentifierManager") as? NSObjectProtocol.Type else {
    return nil
}
0
jscs On

Looks like you need to cast from AnyObject.Type to AnyObject first to convince the compiler that you're talking about an instance (albeit an instance of a metaclass, as you know):

    guard
        let klass = NSClassFromString("ASIdentifierManager"),
        let managerClass = klass as AnyObject as? NSObjectProtocol else
    {
        return nil
    }

I'm not sure whether this should be considered a compiler bug or not. I'd bet not, and that there's some Swiftian reason that NSObjectProtocol does not apply to ObjC type objects when in a Swift context.