如果我在Swift中有一个数组,并尝试访问一个越界的索引,有一个不足为奇的运行时错误:
var str = ["Apple", "Banana", "Coconut"]
str[0] // "Apple"
str[3] // EXC_BAD_INSTRUCTION
然而,我本以为有了Swift带来的所有可选的链接和安全性,做这样的事情是微不足道的:
let theIndex = 3
if let nonexistent = str[theIndex] { // Bounds check + Lookup
print(nonexistent)
...do other things with nonexistent...
}
而不是:
let theIndex = 3
if (theIndex < str.count) { // Bounds check
let nonexistent = str[theIndex] // Lookup
print(nonexistent)
...do other things with nonexistent...
}
但事实并非如此——我必须使用ol' if语句来检查并确保索引小于str.count。
我尝试添加我自己的下标()实现,但我不确定如何将调用传递给原始实现,或者访问项目(基于索引)而不使用下标符号:
extension Array {
subscript(var index: Int) -> AnyObject? {
if index >= self.count {
NSLog("Womp!")
return nil
}
return ... // What?
}
}
不知道为什么没有人,已经提出了一个扩展,也有一个setter自动增长数组
extension Array where Element: ExpressibleByNilLiteral {
public subscript(safe index: Int) -> Element? {
get {
guard index >= 0, index < endIndex else {
return nil
}
return self[index]
}
set(newValue) {
if index >= endIndex {
self.append(contentsOf: Array(repeating: nil, count: index - endIndex + 1))
}
self[index] = newValue ?? nil
}
}
}
使用很容易,工作在Swift 5.1
var arr:[String?] = ["A","B","C"]
print(arr) // Output: [Optional("A"), Optional("B"), Optional("C")]
arr[safe:10] = "Z"
print(arr) // [Optional("A"), Optional("B"), Optional("C"), nil, nil, nil, nil, nil, nil, nil, Optional("Z")]
注意:你应该理解在swift中增长数组时的性能成本(在时间/空间上)-但对于小问题,有时你只需要让swift停止自己的swift
在我的用例中,我用nils填充了数组:
let components = [1, 2]
var nilComponents = components.map { $0 as Int? }
nilComponents += [nil, nil, nil]
switch (nilComponents[0], nilComponents[1], nilComponents[2]) {
case (_, _, .Some(5)):
// process last component with 5
default:
break
}
还可以查看Erica Sadun / Mike Ash的safe:标签的下标扩展:http://ericasadun.com/2015/06/01/swift-safe-array-indexing-my-favorite-thing-of-the-new-week/