Self.Type cannot be directly converted to AnyClass in extension to objective-c class in swift

不想你离开。 提交于 2019-12-08 16:37:33

问题


I'm trying to create fabric method to create UIViewController with correct nib name (to fix iOS8 default initialiser issue). To do it I have added extension:

extension UIViewController {    
    class func create() -> Self {
        if #available(iOS 9.0, *) {
            return self.init()
        } else {
            let clsName = NSStringFromClass(self).componentsSeparatedByString(".").last!
            return self.init(nibName: clsName, bundle: nil)
        }
    }
}

However compiler issues error: Cannot convert value of type 'Self.Type' to expected argument type 'AnyClass' (aka 'AnyObject.Type') in NSStringFromClass(self).

To fix it another extension method can be added and code rewritten to:

extension UIViewController {
    private class var nibNameForInitializer:String {
        return NSStringFromClass(self).componentsSeparatedByString(".").last!
    }
    class func create_() -> Self {
        if #available(iOS 9.0, *) {
            return self.init()
        } else {
            return self.init(nibName: self.nibNameForInitializer, bundle: nil)
        }
    }
}

However I want to understand the problem with first variant.

As I understand, method returning Self is a kind of generic method. Self can be used in many contexts (e.g. class, struct, protocol, etc), however Self.Type matches AnyClass only for classes.

In my case, compiler should know that Self refers to UIViewController and all its subclasses (since it is inside UIViewController extension), so Self.Type must be convertible to AnyClass.

Do I miss anything, or it is correct behaviour, since compiler doesn't perform any additional type analysis for Self?


回答1:


This looks like a bug or an (unnecessary) restriction, so you might consider to file a bug report at Apple. It happens only for type methods with return type Self. As a workaround, you can write

let clsName = NSStringFromClass(self as! AnyClass).componentsSeparatedByString(".").last!

which compiles and seems to work as expected.

But there is a simpler way to get the same result:

// Swift 2:
let clsName = String(self)
// Swift 3:
let clsName = String(describing: self)



回答2:


Perhaps it is a bug, try forcing a downcast, that is how I had to get this to work:

let clsName = NSStringFromClass(self as! AnyClass).componentsSeparatedByString(".").last!


来源:https://stackoverflow.com/questions/33567189/self-type-cannot-be-directly-converted-to-anyclass-in-extension-to-objective-c-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!