Question: Assigning a Variable to an Underscore in Swift

Question

Assigning a Variable to an Underscore in Swift

Answers 2
Added at 2017-01-01 06:01
Tags
Question

After researching stackoverflow about underscores in Swift I understand that an underscore means a) ignore this function and b) you can omit the parameter name when using the method. What I don't understand is what happens if we assign a variable to an underscore? By assigning an underscore to a variable, this silences the compiler warning from Xcode that reads "result of initializer is unused" but it doesn't show warnings if you don't use this variable in any way.

Is this variable still created and stored in memory or is it ignored by the compiler all together as if it were a line of code that is commented out?

For example:

func test_ToDoItem_TakesTitle(){

        let firstToDoItem = ToDoItem(title: "First Instance Title")

        _ = ToDoItem(title: "First ToDoItem instance")

        XCTAssertEqual(firstToDoItem.title, "First Instance Title")

    }

Is the following line of code created and stored in memory or ignored:

 _ = ToDoItem(title: "First ToDoItem instance")

Hopefully this question makes sense because I'd like to become mindful of how each piece of memory is used in Xcode.

Answers to

Assigning a Variable to an Underscore in Swift

nr: #1 dodano: 2017-01-01 06:01

This test shows that the object is created and then destroyed when the object goes out of scope:

class ToDoItem {
    var title = ""

    init(title: String) {
        self.title = title
    }

    deinit {
        print("deinit \(title)")
    }
}

func test() {
    print("test")

    _ = ToDoItem(title: "First")
    _ = ToDoItem(title: "Second")

    print("end test")
}

func callTest() {
    print("calling test()...")
    test()
    print("back from test()")
}

callTest()

Output:

calling test()...
test
end test
deinit Second
deinit First
back from test()

Extended test:

func test() {
    print("test")

    _ = ToDoItem(title: "Item 1")
    for i in 2...4 {
        _ = ToDoItem(title: "Item \(i)")
    }
    _ = ToDoItem(title: "Item 5")

    print("end test")
}
calling test()...
test
deinit Item 2
deinit Item 3
deinit Item 4
end test
deinit Item 5
deinit Item 1
back from test()

Notice that items 2, 3 and 4 are deinitialized as they go out of scope in each loop. Items 1 and 5 are deinitialized when they go out of scope when test() completes.

nr: #2 dodano: 2017-01-01 06:01

Is this variable still created and stored in memory or is it ignored by the compiler all together as if it were a line of code that is commented out?

It all depends on the implementation of the ToDoItem class.

The line seems to be redundant on first sight. But think about this, what if there is something that is in the initializer of ToDoItem that you want executed? The only way to have that executed is to create a new instance of ToDoItem but writing ToDoItem(...) alone would cause a warning. That's why you use the wildcard pattern to silence the warning.

This is especially useful in CoreData. Sometimes you only want to save a new managed object without changing any of the properties. You would write:

_ = MyEntity(entity: ..., insertInto: ...)

because you just want the side effect of the initializer - saving a new managed object.

If the initializer of ToDoItem assigns self to something else, then yes, the ToDoItem will be in memory. For example,

SomeClass.someStaticProperty = self

If you don't do that, ToDoItem will be deinitialized

Source Show
◀ Wstecz