2017-09-06 35 views
1

我注意到在iOS代码中有一个烦人的模式。在新的视图控制器被实例化之后,视图控制器被传递来自先前的视图控制器的参数,所以最终得到如下例子的代码。 SecondViewController的属性实际上不是可选的,但它们必须是可空的,因为您将它们设置为prepare(for:sender:)如何避免Swift UIViewControllers中的可选检查?

class FirstController : UIViewController { 
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
     ... 
     let vc = segue.destination as! SecondController 
     vc.thing = getThing() 
     vc.abc = "123" 
     ... 

class SecondController : UIViewController { 
    var thing: Thing? 
    var abc: String? 
    override func viewDidLoad() { ... } 
    func foo() { 
     guard let thing = self.thing else { return } 
     ... 
    } 
    func bar() { 
     blahBlah(abc!) 

,似乎有与实例变量两个选项...

  1. 让他们T?并有guardif let随处可见。
  2. 使他们v T!,并希望没有被设置之前调用。

所以也许我的问题归结为:在这里做#2安全吗?是否有保证在第一个控制器中prepare(for:sender:)之前UIViewController没有任何内容被调用?

编辑:我不喜欢选项1的一个原因是它几乎在每种方法中都会导致guards,因为它们可能是不必要的。看起来像一个代码味道给我。在纯Swift类中,您将通过thingabcinit(...),并且它们是非可选的,但在这里不能这样做。我们正在处理一个奇怪的情况,Swift已被添加到Objective C中设计的东西中。

回答

0

理论上讲,如果在prepare之前设置所有这些变量,那么它应该没问题。但是,使用警卫并让任何地方都有问题?这只是迅捷的方式。即使现在做数字2是安全的,谁又会说它将来不安全?或者我们不知道的一些奇怪的行为发生,并且它实际上并不安全,或者您也有其他人在项目中工作,他们不知道这一点,并忘记在继续之前设置其中一个变量,并且它结束造成事故。因此,1号线是迄今为止最安全的路线,您可以放心地休息,因为它知道它不会因此而崩溃。

+3

请记住,您可能希望它崩溃,因为这意味着代码中存在错误。使用选项#2可能会更好,因为您不需要所有的检查,并且如果应用程序崩溃(在开发和/或测试过程中,那么这很好,因为您在应用程序中发现了一个错误)。 – rmaddy

+0

@rmaddy这是一个非常公平的点,我同意。然而,对于发行版,我绝对不想使用选项2.特别是如果您有成千上万的用户在使用您的应用程序,您将永远无法确定会发生什么情况,将其与项目中的多个开发人员编码结合在一起,并且让您头疼。 – TNguyen

+1

发布与它有什么关系?如果您的应用程序已使用选项2进行测试并且工作正常,那么这是正确的解决方案。如果你释放它,并且它由于选项2而突然中断,那么你做了一个糟糕的工作测试。这仍然是需要修复的代码中的一个错误。这并不意味着使用选项2是错误的。 – rmaddy