Ответ 1
Обновление Swift 4
В Swift 4 благодаря возможность иметь предложения where
для связанных типов, Collection
теперь предусматривает, что Indices
Element
- это тот же тип, что и Collection
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
}
}
Swift 3
Протокол Sequence
в Swift 3 по-прежнему имеет метод 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
):
/// 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
в настоящее время нет способа выразить, что Indices
Iterator.Element
имеет тип Index
(это будет возможно в будущей версии Swift), компилятор не знает, что вы можете передать что-то типа Index
в contains(_:)
. Это связано с тем, что в настоящее время вполне возможно, чтобы тип соответствовал Collection
и реализовал Indices
с любым типом элемента, который он хочет.
Поэтому решение состоит в том, чтобы просто ограничить расширение, чтобы Indices
имел элементы типа Index
, позволяя вам передать Index
в contains(_:)
:
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
}
}