无法分配 _ArrayProtocol 中的项目 [英] Can't assign the item in _ArrayProtocol

查看:28
本文介绍了无法分配 _ArrayProtocol 中的项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 ParseLiveQuery 检索数据

我的问题是...我无法分配数组中的项目...

导入基础导入解析导入 ParseLiveQuery扩展 _ArrayProtocol 其中 Iterator.Element == PFObject {变异 func updateWithEvent(event: Event) {切换事件{案例.created(让对象):追加(对象)case .entered(let object):追加(对象)案例.deleted(让对象):如果让 index = index(of: object) {删除(在:索引)}案例.left(让对象):如果让 index = index(of: object) {删除(在:索引)}案例.更新(让对象):如果让 index = index(of: object) {//我得到一个错误:无法通过下标分配:下标是仅获取的自我[索引] = 对象}}}}

问题来了

 case .updated(let object):如果让 index = index(of: object) {//我得到一个错误:无法通过下标分配:下标是仅获取的自我[索引] = 对象}}

有人知道吗?

解决方案

首先,您应该小心处理内部类型和协议.协议名称前缀的下划线 (_ArrayProtocol) 告诉我们这一点;这是一个内部协议,这意味着它可能会在未来的 Swift 更新中在没有警告的情况下提示更改(因为使用 Swift 的开发人员不应依赖于内部协议的直接/显式用法).

<块引用>

内部协议_ArrayProtocol: RangeReplaceableCollection, ...

来自 swift/stdlib/public/core/ArrayType.swift.

<小时>

现在,至于你的错误,错误信息很能说明问题

<块引用>

不能通过subscript赋值:subscript是get-only

即,_ArrayProtocolsubscript 没有可用的 setter(例如,通过默认实现:因为您使用 _ArrayProtocol 作为类型本身在您的扩展名中).它确实有 subscript 的 setter 蓝图,但不存在它的默认实现,而 getter 的默认实现可从 RangeReplaceableCollection 获得.

因此对于这种特殊情况,如果您想在 index 处替换 selfElement,您可以例如利用变异的 replaceSubRange(_:, with:)RangeReplaceableCollection 的 code> 方法可被符合 _ArrayProtocol 的类型访问,因为协议本身符合 RangeReplaceableCollection:

replaceSubrange(index...index, with: [object])

如果我们暂时离开直接使用内部协议不合适的主题,我们可以构建一个实现此修复的示例,一个实际可以验证的示例(与您在你的问题……)

enum Foo {创建案例(Int)案例输入(Int)案例已删除(Int)案例左(Int)案例更新(Int)}//不要直接使用这个 _internal_ 协议!!扩展 _ArrayProtocol 其中 Iterator.Element == Int {变异 func updateWithEvent(event: Foo) {切换事件{案例.created(让对象):追加(对象)case .entered(let object):追加(对象)案例.deleted(让对象):如果让 index = index(of: object) {删除(在:索引)}案例.left(让对象):如果让 index = index(of: object) {删除(在:索引)}案例.更新(让对象):如果让 index = index(of: object) {replaceSubrange(index...index, with: [object])}}}}

但话又说回来,你不应该对内部协议实现这样的扩展.考虑实现对公共类型/协议的扩展,例如作为 Array 的扩展,限制为符合 EquatableElement:

enum Foo{创建案例(T)输入案例(T)案例删除(T)案例左(T)案例更新(T)}扩展数组 where Element: Equatable {变异 func updateWithEvent(event: Foo) {切换事件{案例.created(让对象):追加(对象)case .entered(let object):追加(对象)案例.deleted(让对象):如果让 index = index(of: object) {删除(在:索引)}案例.left(让对象):如果让 index = index(of: object) {删除(在:索引)}案例.更新(让对象):如果让 index = index(of: object) {自我[索引] = 对象}}}}

请注意,与使用内部 _ArrayProtocol 的具体类型(如在您自己的扩展中,self 的用法)相比,它没有用于 <代码>下标,Array,另一方面,确实,这意味着您可以在将扩展应用于 时应用原始的简单元素替换 self[index] = object>数组.

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?

解决方案

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.

这篇关于无法分配 _ArrayProtocol 中的项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆