我在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()功能。相反,它为我提供了此方法的以下语法:
contains()
indices.contains(where: { (<#Self.Indices.Iterator.Element#>) -> Bool in <# code ??? what should it do??? #> })
问题是我不知道块中应包含什么。请帮忙进行迁移吗?
在夫特4,由于能力具有where对相关联的类型的子句,Collection现在强制执行Indices的Element类型是相同的类型Collection的Index。
where
Collection
Indices
Element
Index
因此,这意味着我们只能说:
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 } }
SequenceSwift 3中的协议仍然有一个contains(_:)方法,如果序列是Equatable元素,则该方法可以接受序列的元素:
Sequence
contains(_:)
Equatable
extension Sequence where Iterator.Element : Equatable { // ... public func contains(_ element: Self.Iterator.Element) -> Bool // ... }
您遇到的问题是由于Collection的indices财产要求类型发生了变化。在Swift 2中,它是类型Range<Self.Index>-但是在Swift 3中,它是类型Indices(Collection协议的关联类型):
indices
Range<Self.Index>
/// 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传递Index给contains(_:)。这是因为,当前完全有可能使类型符合Collection并实现所需Indices的 任何 元素类型。
Iterator.Element
因此,解决方案是简单地限制你的扩展,以确保Indices 不会 有类型的元素Index,让你传递index到contains(_:):
index
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 } }