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

Swift之可选型

2018-01-26 10:42 218 查看


第一部分:初识可选型

可选类型顾名思义。它表示一个变量有可能有值,也可能没有值(nil)。
可选类型类似于OC指针的nil值,但是OC中的nil只对类有用,而可选择型中nil对所有类型都可用,更安全
可选型的声明的方式是“数据类型+问号”。如:var errorCode :Int? = 404
当要使用一个可选类型的变量时,要在后面加感叹号“!”或者“?”。
不能把一个可选型便量赋值给非可选型的变量, 如:let tempValue = nil //报错
可选型数据一般都是可变的,所以一般情况下,可选型的数据也通常是变量
声明一个可选型的时候,必须是添加?,swift不能隐式的自动推断可选型
代码示例1:
//swift不能用同类中的一个特殊值代表无或者没有,nil代表没有,但是却不能直接使用,如下:
var errorCode :Int = 404
errorCode = nil //报错
//改:使用Int?  声明一个整型可选型
var errorCode :Int? = 404
errorCode = nil //将其声明为为可选型变量才能赋值为nil
1
2
3
4
5
6
7


第二部分:可选型解包

解包:可选型数据,意味着其值是可以为nil的,所以不可以直接使用
//直接使用
var errorCode: String? = "404"
print(errorCode)
//"The errorCode is" +errorCode //直接使用显式可选型会编译不通过,报错
1
2
3
4
解包方法1:普通的if判断,不方便
if(errorCode != nil){
"The errorCode is " + errorCode!
}else{
"No error"
}
1
2
3
4
5
解包方法2:强制解包,使用感叹号“!”,存在错误风险。
//一般情况下,我们在确定使用的可选型变量不会是nil,才通过!强制解包并使用
var errorCode: String? = "404"
"The errorCode is " + errorCode!
1
2
3
解包方法3:尝试解包,使用问号“?”,较为安全
//当不确定使用的可选型变量是否是nil,通过?执行调用方法等操作,意味着不为nil时才可以执行成功
var errorCode: String? = "404"
"The errorCode is " + errorCode?
1
2
3
解包方法4:if-let解包
//当我们希望在可选型为nil时候执行别的代码,更适合使用使用if let方式解包

if let unwrappedErrorCode = errorCode{
//unwrappedErrorCode 是经过解包的数据,得到非nil值
"The errorCode is" + unwrappedErrorCode
}
1
2
3
4
5
6
//解包方法4的改进:可以使用原来的变量名
if let errorCode = errorCode{
//errorCode 是经过解包的数据,得到非nil值
//括号内的errorCode 只在此括号内使用
"The errorCode is" + errorCode
}else{
//处理nil情况
}
1
2
3
4
5
6
7
8
9
注意1:隐式声明的可选型不需要解包,同样可能因为nil报错(详情请看第五部分)
var blog:String! = “elloWord"
// blog = nil"My blog is " + blog
1
2
注意2:if-let同时解包多个变量,同时因为使用了if,也可以增加判断逻辑
if let errorCode = errorCode, errorMessage = errorMessage where errorCode == "404" {
print("Page not found")
} else {
print("No error")
}
1
2
3
4
5


第三部分:可选链 Option chaining

可选链的使用简化了可选型的使用。在某些情况下可以避免if-let 解包的使用,而是通过尝试解包(使用问号?)或者强制解包(感叹号!)来使用操作对象 

示例:
var errorCodeStr: String? = "Hello, playground"
//errorCodeStr.uppercaseString ; errorCodeStr是可选型不能直接使用,需要解包如下:
if let errorCodeStr = errorCodeStr{
errorCodeStr.uppercaseString
}
1
2
3
4
5
但是依然可以简化,如下:
//推荐写法:使用?尝试解包,如果成功就会将字符串大写
errorCodeStr?.uppercaseString
//不安全写法,当errorCode为nil时报错,除非我们确保errorCodeStr不为nil才能这样写
errorCodeStr!.uppercaseString
1
2
3
4
基于这样的使用,可能会出现类似 Person?.address?.addressName 的使用,这就构成了可选链,调用链中任何一个节点为nil,整个调用都会失败,返回nil,使用?是安全的。


第四部分:nil coalesce 空合并运算符

空合并运算符:解决解包之后的存值问题 

示例1:
var uppperCaseErrorStr = errorCodeStr?.uppercaseString
//uppperCaseErrorStr此时是一个可选型变量,不需要显示声明,因为后面的表达式是可选型
//实现解包同时实现了大写
if let errorCodeStr  = errorCodeStr?.uppercaseString{
errorCodeStr
}
1
2
3
4
5
6
7
//示例2:
var errorMessage: String? = nil
let message: String
if let errorMessage = errorMessage{
message = errorMessage
}else{
message = "no error"
}
1
2
3
4
5
6
7
改进示例2:使用三目运算符
let message2 = errorMessage == nil ? "no errror" :errorMessage;
1
改进示例2:使用空合并运算符??,如果errorMessage有值,使用errorMessage!赋值
//??是空和并运算符
let message3 = errorMessage ?? "no error"
1
2


第五部分:隐式可选型

区别于显式可选型的创建:类型+?,创建隐式可选型使用:类型+!
隐式可选型变量使用时,相当于其后面自带了一个感叹号,可以直接赋值给一个非可选型变量,但是隐式可选型依然保持可选型的特性,可以被赋值为nil,这就体现出来隐式可选类型的优点,即可用被赋值为nil,也可以不用每次显式的解包
隐式解析可选类型还可以在类中做属性,解决循环引用问题。 

示例:
var errorMessage: String! = nil
errorMessage = "not found"
//这里errorMessage是隐式可选型,使用时候不需要显式的解包,但是如果errorMessage为nil就会报错
"The error is " + errorMessage
1
2
3
4


第六部分:可选型使用的其他示例

示例1.
var error1:(errorCode: Int, errorMessage: String?) = (404 , "page not found")
error1.errorMessage = nil
//error1 = nil 整个元组并非可选型,不能使用nil赋值
1
2
3
示例2.
var ageInt: String = "xyz"
//使用强制转换之后,age是可选型,需要按照可选型的规则去使用
var age = Int(ageInt)
if let age = age where age < 20{
print("you are a tennager!")
}
1
2
3
4
5
6
示例3.
var greeting = "hello"
//rangeString 返回一个可选型,需要按照可选型的规则去使用
greeting.rangeOfString("ll") //2..<4
greeting.rangeOf3String("oo")//nil
1
2
3
4


最后小结:

有了可选型,你在声明隐式可选变量或特性的时候就不用指定初始值,因为它有缺省值nil。尤其是在一个创建一个累的属性的时候。
由于隐式解析可选的值会在使用时自动解析,所以没必要使用操作符!来解析它。但是有可能运行时报错。
使用可选链会选择性的执行隐式解析可选表达式上的某一个操作。如果值为nil,就不会执行任何操作,因此也不会产生运行错误。
非可选型的变量或者常量不可能赋值为nil,所以不能使用:notOptioalValue != nil,判断是否nil。这是可选型和非可选型数据的一个明显区别
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: