Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift computed property to return copy of underlying array

Tags:

swift

I have a model class written in Objective-C that I'm converting to Swift. It contains an NSMutableArray internally, but the method signature for the getter, as well as the actual return value, are NSArray. When called, it creates an immutable copy to return.

Essentially, I want callers to be able to iterate/inspect the container, but not modify it. I have this test snippet:

class Container {
    internal var myItems = [String]()

    func sayHello() {
        "I have: \(myItems)"
    }
}

let cont = Container()

cont.myItems.append("Neat") // ["Neat"]

cont.sayHello() // This causes sayHello() to print: "I have: [Neat]"

var isThisACopy = cont.myItems

isThisACopy.append("Huh") // ["Neat", "Huh"]

cont.sayHello() // This ALSO causes sayHello() to print: "I have: [Neat]"

I've been trying to find a way to override the getter for myItems so that it returns an immutable copy, but can't seem to determine how.

Attempt #1

This produces a compiler error: Function produces expected type '_ArrayBuffer<(String)>'; did you mean to call it with '()'?

internal var myItems = [String]() {
    var copy = [String]()
    for item in ... { // What to use in the ...?
        copy.append(item)
    }
    return copy
}

Attempt #2

This also produces a compiler error, because I'm (understandably) redefining the generated getter Invalid redeclaration of 'myItems()':

internal func myItems() -> [String] {
    var copy = [String]()
    for item in myItems {
        copy.append(item)
    }
    return copy
}
like image 230
Craig Otis Avatar asked Sep 11 '14 23:09

Craig Otis


People also ask

What is the difference between computed property and lazy property?

Swift's lazy properties let us delay the creation of a property until it's actually used, which makes them like a computed property. However, unlike a computed property they store the result that gets calculated, so that subsequent accesses to the property don't redo the work.

What are computed properties in Swift?

Computed properties are provided by classes, structures, and enumerations. Stored properties are provided only by classes and structures. Stored and computed properties are usually associated with instances of a particular type. However, properties can also be associated with the type itself.

What is getter and setter in Swift?

Setters and getters in Swift apply to computed properties/variables. These properties/variables are not actually stored in memory, but rather computed based on the value of stored properties/variables. See Apple's Swift documentation on the subject: Swift Variable Declarations.

How do I make a property computed?

Defining a computed property To start, you have to write a variable and explicitly declare the type of the property to help the compiler know what kind of value will be assigned to it. Do not assign a default value. Instead open a bracket after the type declaration and start working on the getter.


2 Answers

Try this:

class Container {
    private var _myItems: [String] = ["hello"]
    internal var myItems: [String] {
        return _myItems
    }
}

let cont = Container()
cont.myItems.append("Neat") //not allowed

It uses a private stored property and a computed property that returns an immutable copy. It's not possible for a stored property to use custom getters.

like image 82
Connor Avatar answered Nov 02 '22 02:11

Connor


A better way to expose mutable properties as immutable:

class Container {
    private (set) internal var myItems: [String]
}
like image 1
an0 Avatar answered Nov 02 '22 03:11

an0