在情节提要中使用 segues 使视图控制器具有非可选属性?
Posted
技术标签:
【中文标题】在情节提要中使用 segues 使视图控制器具有非可选属性?【英文标题】:Using segues in storyboard make a view controller that has non optional properties? 【发布时间】:2017-03-07 18:24:34 【问题描述】:我有一个视图控制器,它有一个属性。
class GameVC: UIViewController
var game:Game?
override func viewDidLoad()
super.viewDidLoad()
要使视图控制器有意义,它必须具有游戏属性。出于这个原因,我希望该属性不是可选的(我也不想在整个使用过程中都不必打开它)。
我目前在此之前在 VC 中覆盖为 segue 做准备并设置游戏属性。这是因为我绝对想使用 segues 和故事板。无论如何我可以让这个视图控制器有一个自定义的 init 并且仍然使用 segues 和 storyboards?
【问题讨论】:
您不能使用自定义初始化,但您可以将属性设置为隐式展开的可选:var game: Game!
。这样你在使用它之前就不必打开它,但是如果你在它被设置为非 nil 值之前尝试使用它会崩溃。
【参考方案1】:
是的。你有两个选择:
在声明中初始化:
class GameVC: UIViewController
let game = Game()
实现init(coder:)
或awakeFromNib
:
class GameVC: UIViewController
let game : Game
required init?(coder aDecoder: NSCoder)
self.game = Game()
super.init(coder:aDecoder)
【讨论】:
【参考方案2】:在我看来,在使用情节提要时没有很好的依赖注入方式。我认为故事板违背了面向对象的设计原则。对于团队中的软件开发,我不建议使用它们,除非是原型设计。
相反,我使用简单的 xib 文件并尝试使屏幕(又名 UIViewControllers)尽可能独立。我还在自己的线框类中实现屏幕之间的导航,以将动画导航与 UIViewController 的主要目的(构建/管理视图树)分开。然后可以注入必要的对象,而不会完全失去使用界面生成器的好处。
例子:
final class MyViewController: UIViewController
convenience override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)
self.init()
convenience required init(coder aDecoder: NSCoder)
self.init()
convenience init()
fatalError("Not supported!")
init(viewModel: ViewModel, wireframe: Wireframe)
self.viewModel = viewModel
self.wireframe = wireframe
super.init(nibName: "MyViewController", bundle: Bundle(for: type(of: self)))
private let viewModel: ViewModel
private let wireframe: Wireframe
override func viewDidLoad()
super.viewDidLoad()
// do something with viewModel
@IBAction func close()
wireframe.close()
let wireframe: Wireframe = ConcreteWireframe()
let viewModel: ViewModel = ConcreteViewModel()
let screen: UIViewController = MyViewController(viewModel: viewModel, wireframe: wireframe)
【讨论】:
【参考方案3】:不,Storyboard(和 XIB 文件)使用 init?(coder:)
来实例化元素,您不能将其他参数传递给此 init。
通常的做法是使用隐式解包选项:
var game:Game!
这样,您可以像使用非可选属性一样使用它,如果在使用前未设置,它将在运行时崩溃。
如果您在prepare(for:sender:)
中设置此属性,它将在viewDidLoad
中准备好,因此可以安全使用。
【讨论】:
同意,但它必须是可选的,否则编译器会强制您在 init 方法中为其赋值。 @DuncanC 是一个隐式解包的可选项,所以不需要在 init 中赋值【参考方案4】:在我的应用中,我只使用类似的东西
var game = Game()
这样它就永远不会是nil
,我可以在继续之前设置值。
【讨论】:
以上是关于在情节提要中使用 segues 使视图控制器具有非可选属性?的主要内容,如果未能解决你的问题,请参考以下文章
Segues 直接从情节提要 xcode 中的视图控制器警告启动