Search code examples
iosarraysswiftcollectionssubscript

Swift Array: subscript with IndexPath - unable to mutate


I'd like to add an extension to array of arrays to retrieve an Element with the IndexPath of size 2:

let array: [[String]] =  ....
let indexPath = IndexPath(indexes: [0, 0])
let string = array[indexPath]

I'm getting an error cannot assign through subscript subscript is get-only while implementing the following extension:

extension Array where Element : Collection, Element.Index == Int {
  subscript(indexPath: IndexPath) -> Element.Iterator.Element {
    get {
      return self[indexPath.section][indexPath.item]
    }
    set {
      self[indexPath.section][indexPath.item] = newValue
    }
  }
}

What is the reason for such an error? How can I add a mutation option to the subscript?


Solution

  • In order to mutate the nested arrays you have to require that

    Element : MutableCollection
    

    instead of Element : Collection.

    You can also define two extensions: a read-only subscript for read-only collections, and a read-write subscript for mutable collections:

    extension Collection where Index == Int, Element : Collection, Element.Index == Int {
        subscript(indexPath: IndexPath) -> Element.Iterator.Element {
            return self[indexPath[0]][indexPath[1]]
        }
    }
    
    extension MutableCollection where Index == Int, Element : MutableCollection, Element.Index == Int {
        subscript(indexPath: IndexPath) -> Element.Iterator.Element {
            get {
                return self[indexPath[0]][indexPath[1]]
            }
            set {
                self[indexPath[0]][indexPath[1]] = newValue
            }
        }
    }