无法分配 _ArrayProtocol 中的项目
Can't assign the item in _ArrayProtocol
您好,我正在尝试使用 ParseLiveQuery
检索数据
我的问题是...我无法分配数组中的项目...
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
}
}
}
}
问题来了
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
}
}
有人知道吗?
首先,您应该小心处理内部类型和协议。协议名称前的下划线 (_ArrayProtocol
) 告诉我们这一点;这是一个内部协议,这意味着它可能会在未来的 Swift 更新中提示更改而不会发出警告(因为使用 Swift 的开发人员不应依赖 direct/explicit 对内部协议的使用)。
internal protocol _ArrayProtocol: RangeReplaceableCollection, ...
来自 swift/stdlib/public/core/ArrayType.swift.
现在,至于你的错误,错误信息很清楚
Cannot assign through subscript
: subscript
is get-only
即,_ArrayProtocol
的 subscript
没有可用的 setter(例如,通过默认实现:因为您在扩展中使用 _ArrayProtocol
作为类型本身).它确实有 setter 用于 subscript
蓝图,但不存在它的默认实现,而 getter 的默认实现可从 RangeReplaceableCollection
.
获得
因此对于这种特殊情况,如果您想在 index
处替换 self
的 Element
,您可以例如利用符合 _ArrayProtocol
的类型可访问的变异 replaceSubRange(_:, with:)
method of RangeReplaceableCollection
,因为协议本身符合 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])
}
}
}
}
但话又说回来,您不应该对内部协议实施这样的扩展。考虑改为实现 public type/protocol 的扩展,例如作为 Array
的扩展,限制为 Element
符合 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
}
}
}
}
请注意,与使用内部 _ArrayProtocol
的具体类型(如在您自己的扩展中,self
的用法)相比,后者没有可用的 setter subscript
、Array
,另一方面,does,这意味着当扩展应用于 Array
.[= 时,您可以应用原始简单元素替换 self[index] = object
43=]
您好,我正在尝试使用 ParseLiveQuery
检索数据我的问题是...我无法分配数组中的项目...
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
}
}
}
}
问题来了
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
}
}
有人知道吗?
首先,您应该小心处理内部类型和协议。协议名称前的下划线 (_ArrayProtocol
) 告诉我们这一点;这是一个内部协议,这意味着它可能会在未来的 Swift 更新中提示更改而不会发出警告(因为使用 Swift 的开发人员不应依赖 direct/explicit 对内部协议的使用)。
internal protocol _ArrayProtocol: RangeReplaceableCollection, ...
来自 swift/stdlib/public/core/ArrayType.swift.
现在,至于你的错误,错误信息很清楚
Cannot assign through
subscript
:subscript
is get-only
即,_ArrayProtocol
的 subscript
没有可用的 setter(例如,通过默认实现:因为您在扩展中使用 _ArrayProtocol
作为类型本身).它确实有 setter 用于 subscript
蓝图,但不存在它的默认实现,而 getter 的默认实现可从 RangeReplaceableCollection
.
因此对于这种特殊情况,如果您想在 index
处替换 self
的 Element
,您可以例如利用符合 _ArrayProtocol
的类型可访问的变异 replaceSubRange(_:, with:)
method of RangeReplaceableCollection
,因为协议本身符合 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])
}
}
}
}
但话又说回来,您不应该对内部协议实施这样的扩展。考虑改为实现 public type/protocol 的扩展,例如作为 Array
的扩展,限制为 Element
符合 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
}
}
}
}
请注意,与使用内部 _ArrayProtocol
的具体类型(如在您自己的扩展中,self
的用法)相比,后者没有可用的 setter subscript
、Array
,另一方面,does,这意味着当扩展应用于 Array
.[= 时,您可以应用原始简单元素替换 self[index] = object
43=]