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

来源:互联网 发布:网络代理地址 编辑:程序博客网 时间:2024/05/16 12:37

首先先让我们来了解下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可选绑定来进行使用。









0 0
原创粉丝点击