如果我在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。
if
str.count
我尝试添加自己的subscript()实现,但是不确定如何将调用传递给原始实现,或在不使用下标符号的情况下访问项目(基于索引):
subscript()
extension Array { subscript(var index: Int) -> AnyObject? { if index >= self.count { NSLog("Womp!") return nil } return ... // What? } }
Alex的回答为该问题提供了很好的建议和解决方案,但是,我偶然发现了一种更好的实现此功能的方法:
extension Collection { /// Returns the element at the specified index if it is within bounds, otherwise nil. subscript (safe index: Index) -> Element? { return indices.contains(index) ? self[index] : nil } }
extension Collection where Indices.Iterator.Element == Index { /// Returns the element at the specified index if it is within bounds, otherwise nil. subscript (safe index: Index) -> Generator.Element? { return indices.contains(index) ? self[index] : nil } }
感谢Hamish提出了Swift 3解决方案。
extension CollectionType { /// Returns the element at the specified index if it is within bounds, otherwise nil. subscript (safe index: Index) -> Generator.Element? { return indices.contains(index) ? self[index] : nil } }
let array = [1, 2, 3] for index in -20...20 { if let item = array[safe: index] { print(item) } }