在Swift中,为什么要使用`as`运算符。它有什么好处?他们为什么要投入?

时间:2015-03-10 18:09:47

标签: ios swift design-patterns casting nsdata

我知道as operator做了什么以及如何使用它们。但我对as运营商的架构方面更加好奇。为什么会这样?原因是什么?它有什么帮助?

示例:

var objectData: NSData = NSUserDefaults.standardUserDefaults().objectForKey("myKey") as NSData

......如果是这样的话会不会更好:

var objectData: NSData = NSUserDefaults.standardUserDefaults().objectForKey("myKey")

3 个答案:

答案 0 :(得分:2)

你有点困惑,因为在Swift 1.2之前,as关键字已经超载了多个含义。 Swift 1.2使这个很多更清晰,因为现在有as的3个版本:asas?as!。 (在以前的版本中,asas!只是as}

在您的示例中(我假设它在1.2之前,否则它将无法编译),您正在使用as同时执行两项操作。

NSUserDefaults.objectForKey的返回类型为AnyObject?,可选AnyObject。也就是说,它可以是任何类型的对象,它可能根本不是对象(因为可能没有为“myKey”键设置值。)

要使用此结果,您需要做两件事 - 打开可选项(即测试它是否包含值),并将AnyObject转换为更有用的类型(在本例中为{{ 1}})。

以下是您可以这样做的方法:

NSData

这是使用if let objectData = NSUserDefaults.standardUserDefaults() .objectForKey("myKey") as? NSData // note the question mark --^ { // use the value } else { // handle the value not being present – perhaps set it to a default value } 暂时测试as?返回的值是否为objectForKey类型。 NSData测试是否存在有效值,以及类型是否正确。

请记住,“myKey”存储的值可能与您想要的类型不兼容。假设您想要if let而不是NSData。你做Int。如果为“myKey”存储的值是字符串“foo”,则无法将其转换为if let intData = NSUserDefaults.standardUserDefaults().objectForKey("myKey") as? Int并且您将收到错误。

如果不使用上面的Int,而是使用as?,则强制 Swift解包值并转换类型而不进行检查。如果一切顺利,那很好。但如果没有值或者数据与类型不兼容,您将获得运行时断言,程序将崩溃。

这非常危险,在Swift 1.2中,as的使用已重命名为as,感叹部分表示转换的危险“强制”。如果您尝试在1.2中编译示例代码,则会出现错误,询问您是as!还是as?

as!关键字仍然适用于始终安全的类型说明。例如,假设您有一个像这样的重载函数:

as

还有一些Swift< - > Objective-C桥接转换,保证始终成功,您也可以使用func f(i: Int?) { println("called with Int") } func f(s: String) { println("called with String") } // try to call f with nil – Swift will complain because it // doesn't know if this is a nil int or a nil string f(nil) // you can tell it which with as: f(nil as Int?) // prints "called with Int" f(nil as String?) // prints "called with String"

as

答案 1 :(得分:1)

as的好处是它确认左侧的对象是右侧的类型。它区分了,例如:

myAnimalReallyADog as Dog

myAnimalReallyACat as Dog

如果没有它,你将不得不使用其他的,可能更冗长的方式来测试对象的演员是否合法。

as概念在许多语言中很常见,并不是Swift独有的,所以它是一个完善的范例,非常有用。

答案 2 :(得分:0)

首先,我们应该知道何时使用它。通常你使用这个操作符来执行" downcast" - 也就是说,操作符尝试将对象引用作为派生类返回 - 如果该对象实际上属于该类,则成功。这意味着,呼叫站点必须对该对象的实际类型进行猜测。这种沮丧也可能失败。

因此,答案实际上是双重的:

正如OldPeculier已经指出的那样,"它是一个完善的范例,显然很有用"。

然而,还有其他更好的设计可以避免可能导致失败的垂头丧气。经常使用垂头丧气是一种代码气味。您应该努力重新考虑您的设计,可能使用协议或类扩展,以便强制使用。