如何遵守MutableCollection?

tom*_*dey 5 macos cocoa cocoa-touch ios swift

我很难找到有关如何遵守MutableCollection. 谷歌在这个话题上完全是空的。

\n\n

例如,我想为GMSPath/添加一致性GMSMutablePath

\n\n
import CoreLocation\nimport GoogleMaps\n\nextension GMSPath: RandomAccessCollection {\n\n    public var startIndex: Int {\n        return 0\n    }\n\n    public var endIndex: Int {\n        return count\n    }\n\n    public func index(before i: Int) -> Int {\n        return i-1\n    }\n\n    public func index(after i: Int) -> Int {\n        return i+1\n    }\n\n    public subscript(position: Int) -> CLLocationCoordinate2D {\n        return coordinate(at: UInt(position))\n    }\n}\n\nextension GMSMutablePath: MutableCollection {  // Error!\n\n    public override subscript(position: Int) -> CLLocationCoordinate2D {\n        get {\n            return coordinate(at: UInt(position))\n        }\n        set {\n            replaceCoordinate(at: UInt(position), with: newValue)\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

错误:类型“GMSMutablePath”不符合 a)“MutableIndexable”、b)“MutableCollection”。

\n
\n\n

各州的文件MutableCollection

\n\n
\n

要将 MutableCollection 协议的一致性添加到您自己的自定义集合,请升级您的 type\xe2\x80\x99s 下标以支持读取和写入访问。

\n
\n\n

我就是这么做的。

\n\n

MutableCollection继承自MutableIndexable,文档指出:

\n\n
\n

在大多数情况下,最好忽略此协议并使用 MutableCollection 协议,因为它具有更完整的接口。

\n
\n\n

嗯?

\n

tom*_*dey 1

这里的问题是我也遵守RandomAccessCollection而不只是Collection/ MutableCollection。在这种情况下,与文档所承诺的相反,我们要做的不仅仅是提供下标设置器。具体来说,需要实现切片下标。

我最终得到以下结果。典型别名是必要的,因为编译器似乎并不总是能推断出它们。

 extension GMSPath: RandomAccessCollection {

    public typealias Index = Int
    public typealias Indices = DefaultRandomAccessIndices<GMSPath>

    public var startIndex: Index {
        return 0
    }

    public var endIndex: Index {
        return count
    }

    public func index(before i: Index) -> Index {
        return i-1
    }

    public func index(after i: Index) -> Index {
        return i+1
    }

    public subscript(position: Index) -> CLLocationCoordinate2D {
        return coordinate(at: UInt(position))
    }
}

extension GMSMutablePath: MutableCollection {

    public subscript(bounds: Range<Index>) -> RandomAccessSlice<GMSPath> {
        get { return .init(base: self, bounds: bounds) }
        set {
            assert(newValue.count == bounds.count)
            newValue.enumerated().forEach { self[$0] = $1 }
        }
    }

    public override subscript(position: Index) -> CLLocationCoordinate2D {
        get { return coordinate(at: UInt(position)) }
        set { replaceCoordinate(at: UInt(position), with: newValue) }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用 Swift 的条件默认协议实现,我发现很难找出到底需要实现什么。