一、Optional是什么?
Optional可选型的意思是:有值得时候就是值本身,无值的时候就是 nil 。有点内置三目运算法的意思。Optional 是 Swift 出的新类型。它的用法很简单:类型 + ? 。比如 :String?
、Float?
、Int?
由于swift是类型安全性的语言,所以nil本身就是一种类型。因此这里的 String? 和 String 是完全不同的两个类型,前者是 String 类型的可选型
,后者是 String 类型
,
观察如下代码:
可以发现String
类型是不能直接赋值nil
的,以为String
和nil
是两个类型,所以不能直接赋值。本质原因是swift是类型安全型语言,不同类型不能直接转换。
二、Optional解包
var age:String?;
由于age
是可选类型,所以age可能是String类型,也可能是nil类型。所以我们不能直接使用可选类型,因为不同类型赋值会崩溃。如果要使用可选型的值,那么我们就需要:解包
1:强制解包
强制解包很简单,就是在变量后面+ !
就可以了
例如:
var weight:Int?;
print("体重:\(weight!)");
但是运行一下,你会发现:crash了!怎么回事?原来是强制解包引起的。
强制解包
有个前提,那就是你必须保证这个可选型必须是有值的。否则就会出现问题
所以强制解包是不安全的,一不小心为 nil了,可能会导致程序崩溃。
2:妥协式解包
妥协式解包:其实就是通过原始if else
判断语句来解包
var weight:Int?;
//weight = 22;
if let wei = weight {
print("体重:\(wei)");
} else {
print("体重:nil");
}
还可以这样:
var height:Int?; var weight:Int?;
weight = 22; height = 21;
if let wei = weight,let hei = height {
print("体重:\(wei),身高:\(hei)");
} else {
print("体重和身高:nil");
}
注意这里的
if
里面的相当于&
,只有两个都满足才会执行if
中的代码
swif还有这样的骚操作:if let wei = weight,let hei = height, hei == 22 {}
,添加一个限定条件,就像sql语句一样:SELECT name FROM Persons where name = ob
if let wei = weight,let hei = height, hei == 22{ //where被舍弃,变成','了
print("体重:\(wei),身高:\(hei)");
} else {
print("体重和身高:nil");
}
3:空合运算符式解包
空合运算符(Nil Coalescing Operator):??
,看起来有点奇怪。
var name:String?;
print("name = \(name ?? "default_name")"); //name = default_name
??
就是给这个可选类型设置一个默认值,类似于三目运算符
name == nil ? "default_name" : name;
使用??
解包更加便捷吧
三、Optional 的链式调用
实际开发中,业务的调用逻辑比较复杂,可能会有多层嵌套,这个时候每层的Optional都去判断,那么就会比较麻烦。所以Optional 提供了链式调用。比如:ob?.cls?.name?.uppercased()
class OBClass {
var age:String?;
var name:String?;
var cls:OBClass?
}
let ob:OBClass? = OBClass.init()
if let name = ob?.cls?.name?.uppercased() {
print("age = \(name)");
}else {
print("age = nil");
}
可选链式调用: 多个调用可以连接在一起形成一个调用链,如果其中任何一个节点为 nil ,整个调用链都会失败,即返回 nil ,而不会crash。
四、隐式可选类型
我们每次使用到可选类型变量时,都需要加判断或者解包,这样其实比较麻烦,这时可以利用 隐式可选类型
隐式可选类型: 实际也是可选类型,只是人为的给这个变量赋上初始值。它的作用就是,当你可以确定它是有值的,那么可以直接使用变量,而不需要解包那么麻烦
var height:String! = "";
height.append("25"); //直接使用,可以确定height有值
var weight:String? = "";
weight?.append("25"); //需要声明可选类型,不写?就会报错
其中var height:String! = ""
,等号不能不写,而且后面必须设置初始值,否则和?
没有区别了。
五:guard let
1:if
和if let
的区别
常量 如果是可选类型(Optional)
if
判断后还是需要解包
let name: String? = "ob"
let age: Int? = 20
if name != nil && age != nil {
print(name! + String(age!)) // 输出:ob20
}
if let
判断后不需要解包,{ }内一定有值
let name: String? = "ob"
let age: Int? = 20
// if let 连用,判断对象的值是否为'nil'
if let nameNew = name,
let ageNew = age {
// 进入分支后,nameNew 和 ageNew 一定有值
print(nameNew + String(ageNew)) // 输出:ob20
}
if var的用法:
和if let
的区别就是可以在{}内修改变量的值
let name: String? = "ob"
let age: Int? = 20
if var nameNew = name,
let ageNew = age {
// 'var'修饰,可以修改'nameNew'的值,'let'修改的不可以修改
nameNew = "shuyang"
print(nameNew + String(ageNew)) // 输出:shuyang20
}
2:guard let
guard let
和if let
相反,guard let
守护一定有值。如果没有,直接返回。
用if let
凭空多了一层分支,guard let
是降低分支层次的办法
func tests(str: String?,num:Int?) {
//
guard num != 0 else {
print("i != 0")
return
}
//代码执行到这里, num 一定有值
print("num 值为 \(num!)") //num 值为 8
guard let str = str else {
print("str 为 nil")
return
}
//代码执行到这里, str 一定有值
print("str 值为 \(str)") //str 值为 ob
}
tests(str: "ob", num: 8);
不使用
guard let
而直接使用guard
,那么需要为num
解包
六、try catch
在oc中,处理异常有两种情况
第一种:断言,如果条件为假。那么就会主动奔溃,
NSAssert(NO, @"这里一定主动崩溃");
第二种,就是@try
,使用如下:
@try {
NSMutableArray *marr = [[NSArray new]copy];
[marr addObject:@"one"];
} @catch (NSException *exception) {
NSLog(@"%@",exception.name); //发生异常就会来到catch里面
} @finally {
NSLog(@"----"); //一定来到这里
}
使用@try
后,程序不会崩溃。
2:swift中的try catch
enum AgeError:String, Error {
case ErrorOne = "年龄太小"
case ErrorTwo = "年龄太大"
case ErrorThree = "没有年龄"
}
func checkAge(age: Int?) throws -> Bool {
guard let age = age else {
throw AgeError.ErrorThree;
}
guard age > 0 else {
throw AgeError.ErrorOne; //如果年龄小于0,那么跑出异常
}
return true;
}
func testCatch(name:String?) {
do {
let ret = try checkAge(age: -1);
print("检测结果:\(ret)"); //不会执行,直接抛出异常
} catch {
switch error { // 默认有error的变量
case AgeError.ErrorOne :
print(AgeError.ErrorOne.rawValue); // 打印年龄太小
break;
default:
break;
}
}
}
testCatch(name: "sf");
3:try try?和try!
-
try:
会执行函数之后抛出函数 -
try?:
选择类型的执行,当报错的时候,返回nil,不报错的时候返回正常可选型的值检测结果:Optional(true)
-
try!:
可选型的值,相当于是强制解包,如果抛出异常(也会强制解包),导致崩溃