如果我在Swift中有一个数组,并且试图访问一个超出范围的索引,那么会出现一个毫不奇怪的运行时错误:

var str = ["Apple", "Banana", "Coconut"]

str[0] // "Apple"
str[3] // EXC_BAD_INSTRUCTION

然而,我本以为,在Swift带来的所有可选链接和safety的情况下,做以下事情是微不足道的:

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.

我try 添加自己的subscript()实现,但我不确定如何将调用传递给原始实现,或者如何在不使用下标符号的情况下访问项目(基于索引):

extension Array {
    subscript(var index: Int) -> AnyObject? {
        if index >= self.count {
            NSLog("Womp!")
            return nil
        }
        return ... // What?
    }
}

推荐答案

Alex's answer为这个问题提供了很好的建议和解决方案,然而,我碰巧发现了一种更好的实现此功能的方法:

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
    }
}

哈米什得到了the solution for Swift 3分.


实例

let array = [1, 2, 3]

for index in -20...20 {
    if let item = array[safe: index] {
        print(item)
    }
}

Swift相关问答推荐

绑定到可选值的非可选属性?'

如何在向照片添加文本时定义文本对齐、文本背景的Alpha和在文本之前添加图像

如何在realityKit中反转USDZ动画

如何把多个可观测性变成一个完备性?

我在SwiftUI中的动画无法正常工作

在SwiftUI中,我如何确保带有符号的单词不会被拆分为两行?

try 从闭包访问返回的字符串时出现无法将类型 '()' 的返回表达式转换为返回类型 'String'编译器错误

BLE 在 ESP32 和 Iphone 之间发送字符串

有没有更快的方法来循环浏览 macOS 上已安装的应用程序?

在主要参与者中启动分离任务和调用非隔离函数之间的区别

快速递归:函数与闭包

XCUITest 在 TearDown 期间随机失败-无法终止 com.bundle.id

如何让动画变慢 SwiftUI

SwiftUI:从存储在 observableObject 中的数组中删除对象时查看崩溃

RealityKit – 无法加载 ARView(发现为零)

如何在 Swift 中返回 Task 中定义的变量

如何将使用\u{ea12}创建的 Swift 字符串转换回其十六进制值/字符串ea12?

如何使用 Swift 将文本文件逐行加载到数组中?

Swift - 要求实现协议的类是某个类的子类

Swift:长按手势识别器 - 检测轻按和长按