swift自定义下标来安全访问数组

我想每个开发人员都至少经历过一次index-out-of-bounds的报错。就是数组越界,这个大家都懂,就不过多介绍了。下面是个数组越界的例子:

let values = ["A", "B", "C"]
values[0] // A
values[1] // B
values[2] // C
values[3] // Fatal error: Index out of range

既然是下标超过了数组的大小,那我们在取值之前,先检查下标是否超过数组大小。让我们来看下面的几种方案:

  • 通过 if 来判断下标

if 2 < values.count {
    values[2] // "C"
}
if 3 < values.count {
    values[3] // 不会走到这里
}

虽然也可以,但显的就很重复繁琐,每次取值之前都要判断一遍下标。

  • 定义公共函数

既然每次都要检查下标,那就把检查下标的逻辑放在一个函数里

func getValue<T>(in elements: [T], at index: Int) -> T? {
    guard index >= 0 && index < elements.count else {
        return nil
    }
    return elements[index]
}

let values = ["A", "B", "C"]
getValue(in: values, at: 2) // "C"
getValue(in: values, at: 3) // nil

不仅使用泛型支持了任何类型的元素,当数组越界时,还很贴心的返回了 nil,防止崩溃。

虽然很贴心,但每次取值都要把原数组传进去,显的就很冗余。

  • extension

既然每次都要传入数组很冗余,那就把数组的参数给去掉。我们知道 Swift 一个很强大的特性就是 extension,我们给 Array定义个 extension,并把这个函数添加进去。

extension Array {
    func getValue(at index: Int) -> Element? {
        guard index >= 0 && index < self.count else {
            return nil
        }
        return self[index]
    }
}

let values = ["A", "B", "C"]
values.getValue(at: 2) // "C"
values.getValue(at: 3) // nil
  • subscript

虽然看起来好很多了,但可不可以像原生的取值一样, 一个[]就搞定了

extension Array {
    subscript (safe index: Int) -> Element? {
        guard index >= 0 && index < self.count else {
            return nil
        }
        return self[index]
    }
}

values[safe: 2] // "C"
values[safe: 3] // nil

自定义的[safe: 2]和原生的 [2]非常的接近了。但自定义的提供了数据越界保护机制。

  • 应用到 Collection

既然这么棒,岂能数组一人独享,我们把它应用到所有 Collection 协议。看起来是不是很优雅~😉

extension Collection {
    public subscript (safe index: Self.Index) -> Iterator.Element? {
        (startIndex ..< endIndex).contains(index) ? self[index] : nil
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值