问题
Hi I'm trying to retrieve data by using ParseLiveQuery
My problem is...I can't assign the item in Array..
import Foundation
import Parse
import ParseLiveQuery
extension _ArrayProtocol where Iterator.Element == PFObject {
mutating func updateWithEvent(event: Event<PFObject>) {
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) {
//I got an error : Cannot assign through subscript: subscript is get-only
self[index] = object
}
}
}
}
Here is problem
case .updated(let object):
if let index = index(of: object) {
//I got an error : Cannot assign through subscript: subscript is get-only
self[index] = object
}
}
Anyone know about this?
回答1:
First of all, you should be careful working with internal types and protocols. The underscore prefixing the protocol name (_ArrayProtocol
) tells us just this; that it's an internal protocol, meaning it may be prompt for changes without warning in future Swift updates (since developers using Swift should not rely on direct/explicit usage on an internal protocol).
internal protocol _ArrayProtocol: RangeReplaceableCollection, ...
From swift/stdlib/public/core/ArrayType.swift.
Now, as for your error, the error message is quite telling
Cannot assign through
subscript
:subscript
is get-only
I.e., subscript
for _ArrayProtocol
has no available setter (e.g. via a default implementation: since you're using _ArrayProtocol
as a type itself in your extension). It does have setter for subscript
blueprinted, but there exists no default implementation of it, whereas a default implementation for the getter is available from RangeReplaceableCollection
.
So for this particular case, if you want to replace an Element
of self
at index
, you could e.g. make use of the mutating replaceSubRange(_:, with:) method of RangeReplaceableCollection accessible to types conforming to _ArrayProtocol
, as the protocol itself conforms to RangeReplaceableCollection
:
replaceSubrange(index...index, with: [object])
If we for a minute leave the subject of the inappropriateness of working directly with an internal protocol, we can construct an example implementing this fix, an example that can actually be be verified (in contrast to the one you've supplied in your question ...).
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])
}
}
}
}
But then again, you shouldn't implement such an extension to an internal protocol. Consider instead to implement the extension to public type/protocol, e.g. as an extension to Array
constrained to Element
's that conform to Equatable
:
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
}
}
}
}
Note here that in contrast to working with concrete types of the internal _ArrayProtocol
(as in your own extension, usage of self
), which have no available setter for subscript
, Array
, on the other, does, which means you can apply your original simple element replacement self[index] = object
when the extension is applied to Array
.
来源:https://stackoverflow.com/questions/40691327/cant-assign-the-item-in-arrayprotocol