3 回答
TA贡献1865条经验 获得超7个赞
我偶然发现了一种更好的实现此功能的方法:
Swift 3.2和更新版本
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 }}
Swift 3.0和3.1
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 }}
斯威夫特2
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) }}
TA贡献2019条经验 获得超9个赞
如果你真的想要这种行为,它就像你想要一个Dictionary而不是一个数组。字典nil
在访问丢失的密钥时返回,这是有道理的,因为要知道密钥是否存在于字典中要困难得多,因为这些密钥可以是任何东西,在数组中密钥必须在以下范围内:0
to count
。迭代这个范围是非常常见的,你可以绝对肯定在循环的每次迭代中都有一个真正的值。
我认为它不能以这种方式工作的原因是Swift开发人员做出的设计选择。举个例子:
var fruits: [String] = ["Apple", "Banana", "Coconut"]var str: String = "I ate a \( fruits[0] )"
如果您已经知道索引存在,就像在大多数使用数组的情况下一样,这段代码很棒。但是,如果访问标可能可能返回nil
,那么你已经改变了返回类型的Array
的subscript
方法是可选的。这会将您的代码更改为:
var fruits: [String] = ["Apple", "Banana", "Coconut"]var str: String = "I ate a \( fruits[0]! )"// ^ Added
这意味着每次迭代数组时都需要解包一个可选项,或者使用已知索引执行任何其他操作,因为很少有人可以访问超出范围的索引。Swift设计者在访问越界索引时以牺牲运行时异常为代价,选择了较少的可选解包。崩溃比nil
你在某个地方没想到的逻辑错误更可取。
我同意他们的观点。因此,您将不会更改默认Array
实现,因为您将破坏所有需要来自数组的非可选值的代码。
相反,您可以子类化Array
,并覆盖subscript
以返回可选项。或者,更实际地,您可以Array
使用执行此操作的非下标方法进行扩展。
extension Array { // Safely lookup an index that might be out of bounds, // returning nil if it does not exist func get(index: Int) -> T? { if 0 <= index && index < count { return self[index] } else { return nil } }}var fruits: [String] = ["Apple", "Banana", "Coconut"]if let fruit = fruits.get(1) { print("I ate a \( fruit )") // I ate a Banana}if let fruit = fruits.get(3) { print("I ate a \( fruit )") // never runs, get returned nil}
Swift 3更新
func get(index: Int) ->
T?
需要被替换 func get(index: Int) ->
Element?
- 3 回答
- 0 关注
- 606 浏览
添加回答
举报