为什么Swift 2倾向于强行打开选项?

时间:2015-12-29 02:52:47

标签: ios swift2 xcode7 optional-values forced-unwrapping

我不再看到Xcode抱怨某些事情需要选项("?")。现在它总是被迫解开(爆炸"!")。当我们现在强行打开包装时,有没有理由再使用选项?

2 个答案:

答案 0 :(得分:1)

当你写下你不再看到Xcode抱怨"某些事情需要选项时,我真的不知道你的意思。现在它总是被强行打开" 。这两句话相互矛盾:

  • 您可能拥有您想要的非可选变量,但是一旦您了解了使用它们的所有好处,可选项就非常好。
  • 如果您的财产不是可选的,那么根据定义,它不需要任何解包。

或许你的想法是,当你实际强制解包选项时,Xcode似乎不太经常抱怨,或者,作为Xcode的坏习惯,提示你强行打开包装以避免编译时错误。这通常是因为Xcode在编译时无法知道您刚编写的代码会在运行时破坏您的应用程序。

Xcode似乎有时只有一个单一的目的,它的&#34;智能提示&#34;:即免除编译时错误。如果您尝试将select t1.*,t2.idx,t2.belongTo,t2.datetime1 from table1 t1 inner join ( select t11.idx,t11.belongTo,t11.datetime1,count(*) as row_number from table2 t11 inner join table2 t12 on t11.belongTo=t12.belongTo and t11.datetime1 <= t12.datetime1 group by t11.belongTo,t11.datetime1 ) t2 /*this table will create row_number based on max datetime value for each belongTo*/ on t1.idx=t2.belongTo where t2.row_number=1 类型的值(可选String?)分配给String类型,Xcode将提示您编译错误并询问您是否要添加强制解包运算符String。你说,智能Xcode?嗯,Xcode很适合很多东西,但是决定你如何解开你的选择权,不管怎样,其中之一就是其中之一。因此,即使Xcode提示您进行各种操作:如果您可以使用可选链接,请执行。

当然可能有例外。对于MVC设计pardigm的控制器部分,通常使用!运算符来执行强制转换&#34; (投射),Xcode有时会告诉您明确使用as!代替as!,例如&#34;您的意思是as ......?&#34; 。在这些情况下,Xcode有时实际上可以知道它在做什么,并推断你试图投射,例如,一个自定义的as!类实例,以键入UIViewController,即,它,...父母班。我说这可能是我使用&#34;强迫&#34;的少数几次之一。标记UIViewController没有复飞;强制转换为我知道的类型,100%确定是可投射的。

但是,让我们留下类型转换/转换的主题,并继续进行可选类型,包装和可选链接。

通常,您应该避免强行展开,除非您明确知道您打开的实体将是非零的。对于一般类属性,变量等,假设您按照您的方式陈述此问题,我将提供以下建议:

  

如果你可以使用条件展开(!if-let,则为零   合并运算符guard-let),然后不使用强制解包(??)。

下面是强制展开危险的一个例子。您可以将第一个!子句(if)视为您使用命令式编程技术编写的某个程序中较小或较大的部分:我们并不真正详细了解如何&#39;名称&#39;结果将持续到运行时,我们的编译器无法真正帮助我们。

if arc4random...

我建议你阅读可选链接,这是Swift中的一个关键主题。

答案 1 :(得分:0)

你是说可可的东西吗?你的意思是隐含地解开?

protocol AnyObject { ... }

所有类隐式符合的协议。

当用作具体类型时,所有已知的@objc方法和属性都可用,分别作为AnyObject的每个实例上的隐式解包 - 可选方法和属性。例如:

class C {
  @objc func getCValue() -> Int { return 42 }
}

// If x has a method @objc getValue()->Int, call it and
// return the result.  Otherwise, return nil.
func getCValue1(x: AnyObject) -> Int? {
  if let f: ()->Int = x.getCValue { // <===
    return f()
  }
  return nil
}

// A more idiomatic implementation using "optional chaining"
func getCValue2(x: AnyObject) -> Int? {
  return x.getCValue?() // <===
}

// An implementation that assumes the required method is present
func getCValue3(x: AnyObject) -> Int { // <===
  return x.getCValue() // x.getCValue is implicitly unwrapped. // <===
}