首先,你應該小心使用內部類型和協議。下劃線前綴協議名稱(_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。 –