在我们使用objective-c表示字符串信息的时候,可以用下面方法书写。
NSString *str = @"lalala";
str = nil;
因为objective-c是弱类型语言,所以这里的str既可以是具体的字符串也可以是nil。但到了Swift中就不可以了,因为Swift是类型安全的语言,一个String类型的变量不可能既能是具体的字符串,又可以为nil(更严格的说String类型的内容只能是字符串)。所以,在Swift中有了可选类型的概念。(其实这一概念也是“借鉴”于其他编程语言,比如C#,只不过在C#中称之为可空类型)
为
为什么引入可选类型?
Swift是一门安全的编程语言. 正如苹果所言, 可选类型就是证明Swift是一门安全的编程语言的一个小例子.Swift的可选类型提供了在编译阶段就检查一些可能在运行时才会出现的常见错误的机制. 下面通过下面的例子更好的诠释一下可选类型的威力.
OC中
考虑下面一个Objective-C中的方法
- (NSString *)findStockCode:(NSString *)company {
if ([company isEqualToString:@"Apple"]) {
return @"AAPL";
} else if ([company isEqualToString:@"Google"]) {
return @"GOOG";
}
return nil;
}
通过findStockCode:
方法可以传入公司的名字,然后得到对应公司的股票代码. 为了方便演示, 这里只返回Apple和Google的代码, 对于其他的传入参数, 统统返回nil.
假设在同一个类中调用findStockCode:
方法:
NSString *stockCode = [self findStockCode:@"Facebook"]; // nil is returned
NSString *text = @"Stock Code - ";
NSString *message = [text stringByAppendingString:stockCode]; // runtime error
NSLog(@"%@", message);
上面的代码是可以编译通过的, 但是因为传入了”Facebook”导致返回值是nil, 当代码开始运行后, 程序就会报错了.
Swift中
当使用Swift中的可选类型时, 上面在运行时才会出现的错误在编译阶段就会报错. 如果使用Swift的代码重写上面的例子,代码如下:
func findStockCode(company: String) -> String? {
if (company == "Apple") {
return "AAPL"
} else if (company == "Google") {
return "GOOG"
}
return nil
}
var stockCode:String? = findStockCode("Facebook")
let text = "Stock Code - "
let message = text + stockCode // compile-time error
print(message)
stockCode被定义成可选类型. 这就意味着它要么是一个String, 要么就是nil. 因为编译器在编译阶段就检测到了潜在的错误(可选类型的值没有被解包: value of optional type String? is not unwrapped)并且提示你去改正, 这段代码就不能够被执行.
从这个例子中可以看到, Swift的可选类型加强了对空值的检查, 并且在编译阶段就给开发者提供了可能的错误信息. 很明显, 可选类型的引入可以让代码的质量变得更好.
解决方案:
1.硬解包
如何让上面的代码正常运行? 很明显, 这里需要判断stockCode是否为空. 代码如下:
var stockCode:String? = findStockCode("Facebook")
let text = "Stock Code - "
if stockCode {
let message = text + stockCode!
print(message)
}
像在Objective-C中一样, 还是使用if来判断stockCode中是否有值. 一旦确定stockCode中肯定有值时, 将一个感叹号(!)加在可选类型变量名后面来解包这个可选类型的变量. 在Swift中, 这叫做硬解包. 即直接在可选类型后面加一个感叹号来表示它肯定有值.
缺点:
上面的例子中, 我们只是自己知道stockCode肯定有值, 所以才直接硬解包了stockCode变量. 但是万一有时候我们的感觉是错的, 那程序在运行时可能会出现严重的错误. 所以Swift中是推荐先检查可选类型是否有值, 然后再进行解包的!
var stockCode:String? = findStockCode("Facebook")
let text = "Stock Code - "
let message = text + stockCode! // runtime error
以上代码在编译阶段不会报错.因为使用了硬解包, 编译器认为可选类型是有值的, 所以编译是通过的. 当代码运行起来时, 知名的错误将会出现: fatal error: Can’t unwrap Optional.None
解决方案:使用可选绑定(Optional Binding)
与硬解包不同, 可选绑定(Optional Binding)是一种更简单更推荐的方法来解包一个可选类型. 使用可选绑定来检查可选类型的变量有值还是没值. 如果有值, 解包它并且将值传递给一个常量或者变量.代码如下:
var stockCode:String? = findStockCode("Facebook")
let text = "Stock Code - "
if let tempStockCode = stockCode {
let message = text + tempStockCode
print(message)
}
if let或者if var是可选绑定的两个关键字. 使用自然语言来描述上面这段代码的话, 意思就是如果stockCode有值,解包它,并且将它的值赋值给tempStockCode, 然后执行下面的条件语句; 如果stockCode为空, 直接跳过条件语句块.
上面的代码可以简化如下:
let text = "Stock Code - "
if var stockCode = findStockCode("Apple") {
let message = text + stockCode
print(message)
}
原文地址:http://www.cocoachina.com/swift/20160810/17330.html?utm_source=tuicool&utm_medium=referral