2016-11-19 38 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。 –