无法在_ArrayProtocol中分配项目

时间:2016-11-19 09:36:22

标签: swift3 swift-extensions

您好我尝试使用ParseLiveQuery检索数据

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

 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

                }
            }

这是问题

<td><input type="text" disabled name="quantity_purchased" id="quantity_purchased_<?php echo $result->po_id; ?>_<?php echo $result->item_id; ?>" value="<?php echo $result->quantity_purchased; ?>"/></td>
<td><input type="text"   name="quantity_received" id="quantity_received_<?php echo $result->po_id; ?>_<?php echo $result->item_id; ?>" required placeholder="Enter Received Items" value="<?php echo $result->quantity_received; ?>"/></td>

有人知道吗?

1 个答案:

答案 0 :(得分:1)

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

internal protocol _ArrayProtocol: RangeReplaceableCollection, ...

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

现在,至于你的错误,错误信息很明显

  

无法通过subscript分配:subscript是get-only

即,subscript _ArrayProtocol没有可用的设置器(例如,通过默认实现:因为您在扩展中使用_ArrayProtocol作为类型本身)。它确实有subscript blueprinted的setter,但是没有默认的实现,而getter的默认实现可以从RangeReplaceableCollection获得。

因此,对于这种特殊情况,如果您要在Element替换self index,则可以例如利用符合_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])
            }
        }
    }
}

但话说回来,你不应该对内部协议实现这样的扩展。相反,请考虑实现对公共类型/协议的扩展,例如作为符合Array的{​​{1}}约束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,{ {1}},另一方面does,这意味着您可以在将扩展程序应用于subscript时应用原始的简单元素替换Array