首先,你应该小心使用内部类型和协议。下划线前缀协议名称(_ArrayProtocol
)告诉我们这个;它是一个内部协议,意味着它可能会在未来的Swift更新中提示没有警告的更改(因为使用Swift的开发人员不应该依赖内部协议的直接/显式用法)。
internal protocol _ArrayProtocol: RangeReplaceableCollection, ...
从swift/stdlib/public/core/ArrayType.swift。
现在,为你的错误,该错误信息是相当有说服力
无法通过subscript
分配:subscript
的就是只
也就是说,subscript
为_ArrayProtocol
没有可用setter(例如,通过默认实现:因为您在扩展中使用_ArrayProtocol
作为自己的类型)。它确实具有蓝图的subscript
的设置器,但不存在默认实现,而获取器的默认实现可从RangeReplaceableCollection
获取。
因此,对于这种特殊情况,如果您想在index
处替换Element
的self
,您可以利用变异replaceSubRange(_:, with:)
method of RangeReplaceableCollection
访问,以符合_ArrayProtocol
类型,协议本身符合RangeReplaceableCollection
:
replaceSubrange(index...index, with: [object])
如果我们一分钟离开直接与内部协议工作的不适当的问题,我们可以构造一个实现这个修复的例子,一个实际上可以被验证的例子(与你在问题中提供的那个相反)。
enum Foo {
case created(Int)
case entered(Int)
case deleted(Int)
case left(Int)
case updated(Int)
}
// do not work directly with this _internal_ protocol!!
extension _ArrayProtocol where Iterator.Element == Int {
mutating func updateWithEvent(event: Foo) {
switch event {
case .created(let object):
append(object)
case .entered(let object):
append(object)
case .deleted(let object):
if let index = index(of: object) {
remove(at: index)
}
case .left(let object):
if let index = index(of: object) {
remove(at: index)
}
case .updated(let object):
if let index = index(of: object) {
replaceSubrange(index...index, with: [object])
}
}
}
}
但是,再次,你不应该实现这样的扩展到一个内部协议。而是考虑实现对公共类型/协议的扩展,例如作为扩展到Array
受限于Element
“符合Equatable
S:这里
enum Foo<T> {
case created(T)
case entered(T)
case deleted(T)
case left(T)
case updated(T)
}
extension Array where Element: Equatable {
mutating func updateWithEvent(event: Foo<Element>) {
switch event {
case .created(let object):
append(object)
case .entered(let object):
append(object)
case .deleted(let object):
if let index = index(of: object) {
remove(at: index)
}
case .left(let object):
if let index = index(of: object) {
remove(at: index)
}
case .updated(let object):
if let index = index(of: object) {
self[index] = object
}
}
}
}
注意,在对比与具体类型的内部_ArrayProtocol
的工作(如在自己的延长,self
使用),其中有subscript
,Array
,另一个为does,这意味着您可以将扩展名应用于Array
时应用原始简单元素替换self[index] = object
。
非常感谢你它完美的工作! –
@sungwookbaek高兴地帮忙。 – dfri
_ArrayProtocol在Siwft 3.1中不再公开可见,但现在可以使用相同类型的要求(这简化了一些事情):http://stackoverflow.com/questions/43338557/does-arraytype-or-arrayprotocol-not-available-在-迅速-3-1。 –