小编典典

在Swift 3的Collection扩展中无法使用index.contains()

swift

我在Swift 2.3中编写了以下扩展名:

extension CollectionType {
    /// Returns the element at the specified index iff it is within bounds, otherwise nil.
    subscript (safe index: Index) -> Generator.Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

但是,事实证明,Swift 3.0没有contains()功能。相反,它为我提供了此方法的以下语法:

indices.contains(where: { (<#Self.Indices.Iterator.Element#>) -> Bool in
    <# code ??? what should it do??? #>
})

问题是我不知道块中应包含什么。请帮忙进行迁移吗?


阅读 268

收藏
2020-07-07

共1个答案

小编典典

Swift 4更新

在夫特4,由于能力具有where对相关联的类型的子句Collection现在强制执行IndicesElement类型是相同的类型CollectionIndex

因此,这意味着我们只能说:

extension Collection {

    /// Returns the element at the specified index iff it is within bounds, otherwise nil.
    subscript (safe index: Index) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

迅捷3

SequenceSwift
3中的协议仍然有一个contains(_:)方法,如果序列是Equatable元素,则该方法可以接受序列的元素:

extension Sequence where Iterator.Element : Equatable {
    // ...
    public func contains(_ element: Self.Iterator.Element) -> Bool
    // ...
}

您遇到的问题是由于Collectionindices财产要求类型发生了变化。在Swift
2中,它是类型Range<Self.Index>-但是在Swift
3中,它是类型IndicesCollection协议的关联类型):

/// A type that can represent the indices that are valid for subscripting the
/// collection, in ascending order.
associatedtype Indices : IndexableBase, Sequence = DefaultIndices<Self>

由于Swift目前尚无法让Collection协议 本身 表达Indicess
Iterator.Element是类型的Index但是在Swift的未来版本中可能会出现这种情况),因此编译器无法知道您可以将type传递Indexcontains(_:)。这是因为,当前完全有可能使类型符合Collection并实现所需Indices
任何 元素类型。

因此,解决方案是简单地限制你的扩展,以确保Indices 不会 有类型的元素Index,让你传递indexcontains(_:)

extension Collection where Indices.Iterator.Element == Index {

    /// Returns the element at the specified index iff it is within bounds, otherwise nil.
    subscript (safe index: Index) -> Iterator.Element? {
        return indices.contains(index) ? self[index] : nil
    }
}
2020-07-07