-1
struct SectionData {
    var items : [LiveCellObjectProtocol] 
    var title: String? = nil
    subscript(index: Int) -> LiveCellObjectProtocol {
        return items[index]
    }
}

extension SectionData{
    init(title: String? = nil){
        self.title = title
        self.items = []
    }
}

class LiveCellTableViewController: UIViewController  {

    var sections: [SectionData] = {
        return [SectionData(title: "aaa"), SectionData(title: "bbb"), SectionData(title: "ccc")]
    }()
}

How do I override sections if I subclass this? I'd like to change the titles.

This doesn't build.

class SomeChild: LiveCellTableViewController {
    override var sections: [SectionData] = {
        return [SectionData(title:  nil), SectionData(title: "Mutual"), SectionData(title: "Connections")]
    }()
}
TIMEX
  • 259,804
  • 351
  • 777
  • 1,080

4 Answers4

1

An override property cannot be a stored property. That's just the way Swift works (and this makes sense if you think about it). I list the possibilities in my book as follows:

  • If the superclass property is writable (a stored property or a computed property with a setter), the subclass’s override may consist of adding setter observers to this property.

  • Alternatively, the subclass’s override may be a computed property. In that case:

    • If the superclass property is stored, the subclass’s computed property override must have both a getter and a setter.

    • If the superclass property is computed, the subclass’s computed property override must reimplement all the accessors that the superclass implements. If the superclass property is read-only (it has just a getter), the override can add a setter.

So the way to do what you want to do here is to override, not the property, but the class's initializer. Here's a highly simplified example:

class C {
    var sections : [Int] = [1,2,3]
}

class CC : C {
    override init() {
        super.init()
        super.sections = [4,5,6]
    }
}

C().sections // [1,2,3]
CC().sections // [4,5,6]
matt
  • 515,959
  • 87
  • 875
  • 1,141
0

Get rid of the equals signs:

var sections: [SectionData] {
  return [SectionData(title: "aaa"), SectionData(title: "bbb"), SectionData(title: "ccc")]
}

That's why Xcode wanted parentheses. With the equals sign, your code block was defining an inline function, and the () calls the function, using the result to initialize your variable. Without the () you're trying to assign a function to an array.

Without the =, you're defining a property with a getter, which (I assume) is what you want.

Uncommon
  • 3,323
  • 2
  • 18
  • 36
  • This does something very different than the original code, and different from the apparent intent as well. The original creates a STORED property and initializes it with the return value of a block, so it can be changed later. Yours creates a COMPUTED property which will always return the same value and can't be changed. – David Berry Mar 21 '17 at 20:42
  • Exactly. It looks to me like a computed property is what was intended. – Uncommon Mar 21 '17 at 20:43
0

You can't override a stored property in swift. You can use private storage and calculated properties to work around the issue. Something like this:

 //: Playground - noun: a place where people can play

import Cocoa

struct SectionData {
    let title: String
}

class ParentClass {

    private let defaultSections = [SectionData(title: "Parent")]

    var sections: [SectionData] {
        return defaultSections
    }

}

class ChildClass: ParentClass {

    private let childSections = [SectionData(title: "Child")]

    override var sections: [SectionData] {
        return childSections
    }

}

// If you wanted a child who appends sections

class AnotherChildClass: ParentClass {

    private let childSections = [SectionData(title: "Child")]

    override var sections: [SectionData] {
        return super.sections + childSections
    }

}

Also, because in your example you're just overriding the parent class functionality and your property is immutable, you could just make it a parameter passed in during init.

//: Playground - noun: a place where people can play

import Cocoa

struct SectionData {
    let title: String
}

class ParentClass {

    let sections: [SectionData]

    init(sections: [SectionData]) {
        self.sections = sections
    }
}

class ChildClass: ParentClass {

}

let parent = ParentClass(sections: [SectionData(title: "Parent")])
let child = ChildClass(sections: [SectionData(title: "Child")])
0

Just change the value in your subclass after you create it, if you're loading it from a storyboard, the easiest place is in awakeFromNib:

class SomeChild: LiveCellTableViewController {
    override func awakeFromNib() {
        super.awakeFromNib()

        sections = [SectionData(title:  nil), SectionData(title: "Mutual"), SectionData(title: "Connections")]
    }
}
David Berry
  • 40,941
  • 12
  • 84
  • 95