【发布时间】:2016-07-09 23:45:49
【问题描述】:
我为我的所有 UIViewController 子类添加了一个方法,允许我从类和它所在的情节提要中实例化它。
所有方法都遵循这种格式:
class func instantiateFromStoryboard() -> CameraViewController? {
let storyboard = UIStoryboard(name: "Camera", bundle: nil)
let initial = storyboard.instantiateInitialViewController()
guard let controller = initial as? CameraViewController else {
return nil
}
return controller
}
相反,我想创建一个协议Instantiatable,它需要上述方法以及一个变量storyboardName: String。
然后,我想扩展此Instantiatable,使其包含与上述类似的实现。我的目标是我可以声明 UIViewController 遵守此协议,而我所要定义的只是 storyboardName。
我觉得我已经接近这个实现了:
protocol Instantiatable {
var storyboardName: String { get }
func instantiateFromStoryboard() -> Self?
}
extension Instantiatable where Self: UIViewController {
func instantiateFromStoryboard() -> Self? {
let storyboard = UIStoryboard(name: storyboardName, bundle: nil)
let initial = storyboard.instantiateInitialViewController()
guard let controller = initial as? Self else {
return nil
}
return controller
}
}
但是,当我尝试添加对 CameraViewController 的一致性时,我收到了错误:
非final类
CameraViewController中的方法instantiateFromStoryboard()必须返回Self以符合协议Instantiatable
我错过了什么?
谢谢。
【问题讨论】:
-
为什么你声明你的函数返回
Self而不是CameraViewController?如果你希望它是通用的,那么它应该返回UIViewController? -
抱歉,我将对其进行更明确的编辑。我希望此方法返回符合
Instantiatable协议的UIViewController的任何子类。 -
然后你可以声明它返回
Instantiatable?或者UIViewController? -
太棒了。我希望返回的对象与子类相同,而不是
UIViewController?。我试过Instantiatable?并得到错误:在类型'Self'上使用实例成员'instantiateFromStoryboard';您的意思是改用“Self”类型的值吗? -
您将遇到的另一个问题是您正在添加一个实例函数,因此您已经需要一个您想要的视图控制器实例才能调用
instantiateFromStoryboard,所以您会不得不说像let camVC = CameraViewController(); camVC.storyboard = "somestoryboard"; let realCamVC = camVC.instantiateFromStoryboard()这样的话——这比它需要的要复杂得多。如果每个故事板只需要一个 VC,则可以使用 nib 文件。
标签: ios swift protocols swift-protocols