10

我正在尝试创建结构方法来创建具有正确 nib 名称的 UIViewController(以修复 iOS8 默认初始化程序问题)。为此,我添加了扩展名:

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)
        }
    }
}

但是编译器发出错误:Cannot convert value of type 'Self.Type' to expected argument type 'AnyClass' (aka 'AnyObject.Type')NSStringFromClass(self).

要修复它,可以添加另一种扩展方法并将代码重写为:

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)
        }
    }
}

但是我想了解第一个变体的问题。

据我了解,方法返回Self是一种通用方法。Self可以在许多上下文中使用(例如类、结构、协议等),但仅Self.Type匹配AnyClass类。

在我的情况下,编译器应该知道Self引用UIViewController及其所有子类(因为它在UIViewController扩展内部),所以Self.Type必须可以转换为AnyClass.

我是否遗漏了什么,或者这是正确的行为,因为编译器不执行任何额外的类型分析Self

4

2 回答 2

12

这看起来像是一个错误或(不必要的)限制,因此您可以考虑向 Apple 提交错误报告。它仅发生在具有返回类型的类型方法上Self。作为一种解决方法,您可以编写

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

它编译并且似乎按预期工作。

但是有一种更简单的方法可以获得相同的结果:

// Swift 2:
let clsName = String(self)
// Swift 3:
let clsName = String(describing: self)
于 2015-11-06T13:03:41.040 回答
4

也许这是一个错误,尝试强制沮丧,这就是我必须让它工作的方式:

let clsName = NSStringFromClass(self as! AnyClass).componentsSeparatedByString(".").last!
于 2015-11-06T13:03:54.337 回答