2017-01-01 2 views
4

После исследования stackoverflow о символах подчеркивания в Swift я понимаю, что подчеркивание означает: a) игнорировать эту функцию и b) вы можете опустить имя параметра при использовании метода. Я не понимаю, что произойдет, если мы назначим переменную подчеркиванию? Назначая знак подчеркивания переменной, это заставляет замолчать предупреждение компилятора из Xcode, которое гласит: «результат инициализации не используется», но он не отображает предупреждения, если вы не используете эту переменную каким-либо образом.Назначение переменной подстроки в Swift

Является ли эта переменная все еще созданной и сохраненной в памяти или она полностью игнорируется компилятором, как если бы это была строка кода, которая была закомментирована?

Например:

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.

+1

Функция все же выполняется, однако, поскольку ссылки на него нет, память будет немедленно возвращена ARC. Вот это [предложение] (https://github.com/apple/swift-evolution/blob/master/proposals/0047-nonvoid-warn.md) для этого поведения –

+0

@CodeDifferent, по-видимому, не сразу. Кажется, подождать, пока элемент не выйдет за рамки. См. Мой ответ для демонстрации. – vacawama

+0

Oh wow @CodeDifferent ссылка, которую вы указали под названием «предложение», является ли это хранилище github с открытым исходным кодом, где люди предлагают предложения для быстрого языка, и Apple читает их? Если это так, я слышал об этом через подкасты, но просто хотел убедиться, что это все. –

ответ

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 деинициализируются, как они выходят из области видимости в каждом цикле. Элементы 1 и 5 деинициализируются, когда они выходят за пределы области, когда завершается test().


Внутри из App

Как Дмитрий Плотников отметил в 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. Они немедленно освобождаются.
+0

Очень важно, не уверен, что вы сделали редактирование, но первый пример имеет смысл. –

+0

О, вау, это определенно придавало больше внимания памяти в отношении сферы. –

4

Является ли эта переменная еще создается и сохраняется в памяти или она игнорируется компилятором все вместе, как если бы он был строкой кода, закомментирована?

Все зависит от реализации класса ToDoItem.

Линия кажется излишней с первого взгляда. Но подумайте об этом, что если в инициализаторе ToDoItem есть что-то, что вы хотите выполнить? Единственный способ выполнить это - создать новый экземпляр ToDoItem, но только одно сообщение ToDoItem(...) вызовет предупреждение. Вот почему вы используете шаблон шаблона, чтобы отключить предупреждение.

Это особенно полезно в CoreData. Иногда вы хотите сохранить новый управляемый объект, не изменяя никаких свойств. Вы должны были бы написать:

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

потому что вам просто нужен побочный эффект инициализатора - сохранение нового управляемого объекта.

Если инициализатор ToDoItem присваивает self что-то еще, тогда да, ToDoItem будет в памяти. Например,

SomeClass.someStaticProperty = self 

Если вы не сделаете этого, ToDoItem будет деинициализируются

+0

Отличный пример, потому что вы описали его в терминах Core Data, которые я хотел бы узнать в будущем. Вопрос, хотя? Будет ли «SomeClass.someStaticProperty = self» создать цикл сохранения или сохранить цикл, созданный только тогда, когда один объект имеет ссылку на совершенно другой объект? @Sweeper –

+1

@ user6510422 Нет, цикл сохранения не будет, поскольку 'someStaticProperty' является статическим. Вы можете установить 'SomeClass.someStaticProperty' в' nil' для деинициализации 'ToDoItem'. _ сохранить цикл, созданный только тогда, когда один объект имеет ссылку на совершенно другой объект? _ Не обязательно.Я думаю, что если объект содержит ссылку на себя, будет создан и цикл сохранения, не говоря уже о том, что существует много видов циклов сохранения. – Sweeper

2

Как vacawama говорил в своем ответе, объект создается, а затем разрушается, когда объект выходит из области видимости.

BUT это относится только к коду, выполненному на детской площадке. При выполнении приложения на Simulator или на устройстве объект немедленно уничтожается. Остерегайтесь!

Я использовал следующий код от ответа 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() 

(К сожалению, я не могу комментировать другой ответ еще, хотя я, хотя это было важным, чтобы поделиться)

+1

Я до сих пор не знаю, как подавить «неиспользуемое» предупреждение, если мне нужно, чтобы объект жил внутри области действия, потому что в этом случае я вынужден назначить его для 'let temp = ...' –

+0

, это кажется быть правильным ответом. по крайней мере, в стремительном 8.2 и стремительном 3 – user3763801

+0

Спасибо, Дмитрий. Я понимаю, что вы не могли прокомментировать мой ответ, но я бы оценил это, если бы кто-то был. Увы, я узнал, потому что кто-то проголосовал, не оставляя комментариев о том, почему. Поскольку мой ответ является принятым, я отмечаю ваши результаты и ссылаюсь на ваш ответ. – vacawama

Смежные вопросы