Kevin Wang
Kevin Wang

Reputation: 682

What is the difference between a Computed Property and a Stored Value Property in Swift?

Question:

What is the difference between the two lines in Row.swift?

Context:

Row.swift

open class Row {

  // Existing code (Good):
  public var cellIdentifier: String { return String(describing self) }

  // The change (Bad):
  public var cellIdentifier: String = String(describing: self)

DifferentRow.swift

public class DifferentRow: Row {

  public override var cellIdentifier: String { return "\(super.cellIdentifier)" }
  // returns the error below

Error:

Cannot override mutable property with read-only property 'cellIdentifier'

Upvotes: 0

Views: 765

Answers (3)

vacawama
vacawama

Reputation: 154711

This:

public var cellIdentifier: String { return String(describing self) }

is defining a computed property. No value is stored. Every time you access cellIdentifier the closure runs and returns the String. It is read-only because only the getter has been provided.

This:

public var cellIdentifier: String = String(describing: self)

is a stored value property and it is read/write.

The error is telling you that you can't replace a property that has read/write capabilities with one that has only read capabilities.

Note: if you are initializing a property with a value, you can't access self because self doesn't represent the class/struct instance until the object is completely initialized. If you made the property a lazy var, you could use self in the initialization, because then the property would be initialized once the first time it is accessed.

You can read more about Swift properties here in the Swift Language Guide

Upvotes: 2

Andreas Oetjen
Andreas Oetjen

Reputation: 10209

I think the error message is quite confusing.

The problem with

public var cellIdentifier: String = String(describing: self)

is the reference to self:

  • When assigning cellIdentifier during definition, self is not guarateed to be fully initialized.
  • Therefore, it is forbiddin to call a function (like String(describing:)) and hand-in the half-initilized self

One solution could be to make cellIdentifier a lazy property:

public lazy var cellIdentifier: String = String(describing: self)

This will automatically delay the function call to the time after initialization has finished.

Upvotes: 0

Fabian
Fabian

Reputation: 5358

You can’t override a “read from and write to”-property with a property which one can only read from.

You can assign a different value:

public override var cellIdentifier: String = “newValue”

or create both a set and a get implementation:

public override var cellIdentifier: String {
    get { return “\(super.cellIdentifier)” }
    set { super.cellIdentifier = newValue }
}

Under Computed Properties read more on this syntax.

Upvotes: 1

Related Questions