2015-11-06 65 views
4

我试图创建结构方法来创建具有正确的笔尖名称(修复iOS8默认初始化程序问题)的UIViewController。要做到这一点我已经添加扩展名:Self.Type不能直接转换为AnyClass扩展到Objective-C类在swift

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

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

因为编译器不为Self执行任何其他类型分析,所以我错过了什么,或者它是正确的行为?

回答

8

这看起来像一个错误或(不必要的)限制,所以你可能会考虑在苹果提交一个错误报告 。对于返回类型为Self的类型方法,仅发生 。作为解决方法,您可以编写

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

编译并似乎按预期工作。

但有一个简单的方法来获得相同的结果:

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

哇,恭喜你在几乎同一时间得到与我一样的答案haha – Knight0fDragon

+0

对于Swift 3,最后一行应该是“let clsName = String(describe:self)”。 – RenniePet

+0

@RenniePet:的确,谢谢。 –

2

也许这是一个错误,请尝试强制向下转换,这就是我必须得到这个工作:

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