如果我在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?
    }
}

当前回答

适用于Swift 2

尽管这个问题已经被回答过很多次了,但我想给出一个更符合Swift编程时尚走向的答案,用Crusty的话来说就是:“先考虑协议”。

• What do we want to do? - Get an Element of an Array given an Index only when it's safe, and nil otherwise • What should this functionality base it's implementation on? - Array subscripting • Where does it get this feature from? - Its definition of struct Array in the Swift module has it • Nothing more generic/abstract? - It adopts protocol CollectionType which ensures it as well • Nothing more generic/abstract? - It adopts protocol Indexable as well... • Yup, sounds like the best we can do. Can we then extend it to have this feature we want? - But we have very limited types (no Int) and properties (no count) to work with now! • It will be enough. Swift's stdlib is done pretty well ;)

extension Indexable {
    public subscript(safe safeIndex: Index) -> _Element? {
        return safeIndex.distanceTo(endIndex) > 0 ? self[safeIndex] : nil
    }
}

不正确,但它给出了一个概念

其他回答

extension Array {
  subscript (safe index: UInt) -> Element? {
    return Int(index) < count ? self[Int(index)] : nil
  }
}

使用上述提到的扩展返回nil,如果任何时候索引超出界限。

let fruits = ["apple","banana"]
print("result-\(fruits[safe : 2])")

结果-无

斯威夫特4

为那些更喜欢传统语法的人提供的扩展:

extension Array {
    func item(at index: Int) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

我对数组做了一个简单的扩展

extension Array where Iterator.Element : AnyObject {
    func iof (_ i : Int ) -> Iterator.Element? {
        if self.count > i {
            return self[i] as Iterator.Element
        }
        else {
            return nil
        }
    }

}

它的设计完美无缺

例子

   if let firstElemntToLoad = roots.iof(0)?.children?.iof(0)?.cNode, 

说实话,我也遇到过这个问题。从性能的角度来看,Swift数组应该能够抛出。 让x = try a[y] 这很好,也可以理解。

你可以试试

if index >= 0 && index < array.count {
    print(array[index]) 
}