在Swift中为Underscore分配变量

时间:2017-01-01 05:10:54

标签: swift xcode

在研究了关于Swift中下划线的stackoverflow之后,我理解下划线意味着a)忽略这个函数,b)你可以在使用这个方法时省略参数名。我不明白如果我们将变量分配给下划线会发生什么?通过为变量分配下划线,这会使来自Xcode的编译器警告静音,这些警告读取"初始化器的结果未使用"但如果你不以任何方式使用这个变量,它就不会显示警告。

这个变量是否仍然被创建并存储在内存中,或者被编译器一起忽略,好像它是一行被注释掉的代码?

例如:

func test_ToDoItem_TakesTitle(){

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

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

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

    }

以下代码行是否已创建并存储在内存中或被忽略:

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

希望这个问题有意义,因为我想要注意Xcode中每个内存的使用方式。

3 个答案:

答案 0 :(得分:4)

  

这个变量是否仍然被创建并存储在内存中,或者被编译器一起忽略,好像它是一行被注释掉的代码?

这完全取决于ToDoItem类的实现。

第一眼看上去似乎是多余的。但想想看,如果你想要执行的ToDoItem的初始化程序中有什么内容会怎么样?执行该操作的唯一方法是创建ToDoItem的新实例,但单独编写ToDoItem(...)会引发警告。这就是你使用通配符模式来消除警告的原因。

这在CoreData中特别有用。有时您只想保存新的托管对象而不更改任何属性。你会写:

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

因为您只想要初始化程序的副作用 - 保存新的托管对象。

如果ToDoItem的初始化程序将self分配给其他内容,则是,ToDoItem将在内存中。例如,

SomeClass.someStaticProperty = self

如果您不这样做,ToDoItem将被取消初始化

答案 1 :(得分:2)

正如vacawama在他的回答中提到的那样,当对象超出范围时,对象被创建然后被销毁。

但是这仅适用于在游乐场中执行的代码。在Simulator或设备上执行app时,会立即销毁对象。 小心!

我使用了vacawama的答案中的以下代码进行测试:

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()

(对不起,我还没有对其他答案发表评论;虽然我认为这是一个很重要的分享)

答案 2 :(得分:1)

此测试显示对象在对象超出范围时创建然后销毁:

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()

输出:

calling test()...
test
end test
deinit Second
deinit First
back from 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()

请注意,第2项,第3项和第4项已取消初始化,因为它们在每个循环中超出范围。当test()完成时,第1项和第5项在超出范围时被取消初始化。

应用内部

正如Dmitry Plotnikov在his answer中指出的那样,上述情况仅适用于Swift游乐场。在应用中,结果是:

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

告诉我们:

  1. 创建对象。
  2. 他们立即获释。