您的位置:首页 > 移动开发 > Swift

iOS编程——Swift语法之 "?" 和 "!"

2015-08-17 15:03 507 查看
首先先让我们来了解下Swift中“nil”的含义:在OC中nil指的是一个空对象,它指向一个不存在的对象的指针;而在Swift中它表示的是一个不确定的值,含义是“值缺失”,"nil"只可以用于optionals类型的,比如下面的代码(结果在注释里):

var oneString = "111"

//Error: Cannot assign a value of type 'nil' to a value of type 'String'
oneString = nil

//Error: Binary operator '==' cannot be applied to operands of type 'String' and 'nil'
if oneString == nil {
println(oneString)
}
可以看到对oneString赋值nil和对nil的比较都会报错,那应该怎么用呢,这就涉及到了optionals(可选)类型:

首先来看一个String方法的API:它对String类型扩展了一个将String转换为Int?的方法:

extension String {
func toInt() -> Int?
}
注意:Int后面跟了一个"?",Int?表示:返回值是一个可选类型的,如果有值就是Int型的,如果没有值,就是“nil”。让我对这个函数测试一下:

let oneString = "111"
let possibleNum = oneString.toInt()

//possibleNum: Optional(111)
println("possibleNum: \(possibleNum)")

//possibleNum can use >
if possibleNum > 1 {
println("possibleNum can use >")
}

//Error: Value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?
let addNum = possibleNum + 10
根据打印很明显看出来:Int?打印出来以后是Optional类型的,它可以用来做比较运算;但是不可以做+运算,报错:Int?没有解包,需要用"?"或者"!"来解包。 解包是神马意思呢,其实很简单就是把optional类型转换为Int类型的:只不过“?”表示转换可能会失败,如果失败就是“nil”;而“!”则是表明一定有值,一定可以转换成功,如果没有对应值使用"!"会导致报错。让我们来一步步测试下:

let oneString = "111"
let possibleNum = oneString.toInt()

//unwrapped value: 111
if possibleNum != nil {
println("unwrapped value: \(possibleNum!)")
}


分析:possibleNum是Int?类型的,上面说过“?”类型的如果值不存在就是“nil”,那反过来:如果不为“nil”,那肯定有值可以解包,所以
possibleNum!会解包成功得到Int类型的值:111,这种方法叫做if语句强制解析;

let oneString = "111"
let possibleNum = oneString.toInt()

//oneNum: 111
if let oneNum = possibleNum {
println("oneNum: \(oneNum)")
}
分析:通过使用if let 来进行赋值得到解包后的值,这种方法叫做可选绑定。只有possibleNum有值才可以解包成功,if语句才会成立。如果possibleNum没值是什么样呢,试一下:

let oneString = "abc"
let possibleNum = oneString.toInt()

if let oneNum = possibleNum {
println("oneNum: \(oneNum)")
}

//possibleNum: nil
println("possibleNum: \(possibleNum)")
分析:possibleNum是Int?类型的,因为转换失败所以是”nil“,if语句不会成立。打印之后是nil。

分析完了"?",让我们再来看一下"!","!"之前说过是保证肯定有值,那来看看用法:

let oneString = "111"
let possibleNum: Int! = oneString.toInt()

//possibleNum: 111
println("possibleNum: \(possibleNum)")

//possibleNum can use >
if possibleNum > 1 {
println("possibleNum can use >")
}

//addNum: 121
let addNum = possibleNum + 10
println("addNum: \(addNum)")
通过代码和日志可以看到,Int!类型的变量possibleNum不同于 "Int?",它可以不经过处理直接用来做+运算,这种带"!"的类型叫做隐式解析可选类型。

为什么要这么做呢?让我们假设一个情况:有一个变量在开始可能是nil设置为了"?“类型,可在第一次赋值之后我们可以肯定它以后都会有值,这样每次使用都要重复的进行判断和解析,效率会非常低。所以就可以声明为”!“类型,以后就不需要重复判断和解析了,效率会提高很多。也就是下面的代码:

let optionalString: String? = "one string"
let convertedString1 = optionalString!//需要用"!"进行解包获取值

let implicitlyUnwrappedOptionalString: String? = "one string"
let convertedString2 = implicitlyUnwrappedOptionalString//不需要用"!"


但是需要注意的是:必须保证有值才可以用"!",否则就会报错,比如下面的代码就是错误的:

let oneString = "abc"
let possibleNum: Int! = oneString.toInt()

//Error: unexpectedly found nil while unwrapping an Optional value
let add = possibleNum + 10


总结一下: "?"和”!“是一种安全类型:可选类型,不同的是"?"使用时需要进行解包处理,解包失败就是“nil”,适用于可能没有值的情形。而"!"使用时不需要解包(在第一次赋值时编译器已经自动解包),但是必须保证有值,否则会报错。两者都可以通过if语句强制解析和if let可选绑定来进行使用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: