2016-11-19 40 views
0

你好我试图通过使用ParseLiveQuery不能在_ArrayProtocol指派的项目

我的问题是检索数据...我不能在数组指定项目..

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 

       } 
      } 

有人知道吗?

回答

1

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

internal protocol _ArrayProtocol: RangeReplaceableCollection, ... 

swift/stdlib/public/core/ArrayType.swift


现在,为你的错误,该错误信息是相当有说服力

无法通过subscript分配:subscript的就是只

也就是说,subscript_ArrayProtocol没有可用setter(例如,通过默认实现:因为您在扩展中使用_ArrayProtocol作为自己的类型)。它确实具有蓝图的subscript的设置器,但不存在默认实现,而获取器的默认实现可从RangeReplaceableCollection获取。

因此,对于这种特殊情况,如果您想在index处替换Elementself,您可以利用变异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使用),其中有subscriptArray,另一个为does,这意味着您可以将扩展名应用于Array时应用原始简单元素替换self[index] = object

+0

非常感谢你它完美的工作! –

+0

@sungwookbaek高兴地帮忙。 – dfri

+0

_ArrayProtocol在Siwft 3.1中不再公开可见,但现在可以使用相同类型的要求(这简化了一些事情):http://stackoverflow.com/questions/43338557/does-arraytype-or-arrayprotocol-not-available-在-迅速-3-1。 –