Чем отличается? а также! в слабой, сильной ссылке в Swift
Я новичок в Swift. У меня есть некоторые вопросы, которые нужно решить, но я не могу сделать это самостоятельно.
Вот какая-то проблема для меня:
class Author {
weak var book: Book?
deinit {
print("Dealloc Author")
}
}
class Book {
var author: Author?
deinit {
print("Dealloc Book")
}
}
var authorObj:Author? = Author()
authorObj!.book = Book()
authorObj!.book!.author = authorObj
Это хорошо компилируется:
class Author {
weak var book: Book?
deinit {
print("Dealloc Author")
}
}
class Book {
var author: Author?
deinit {
print("Dealloc Book")
}
}
var authorObj:Author? = Author()
authorObj!.book = Book()
authorObj!.book?.author = authorObj
authorObj = nil
- Так вы, ребята, можете объяснить для меня, что между ними? а также! в
authorObj!.book?.author = authorObj
а такжеauthorObj!.book!.author = authorObj
?
У меня есть еще два вопроса:
authorObj
сильная ссылка так же, какauthorObj.book.author
, это сильная ссылка тоже? Потому что это не имеетweak
или жеunowned
до вар.Только
authorObj.book
это слабая ссылка. Но когда я назначаюauthorObj
до нуля, все они деиницированы. Зачем? Я назначаю толькоauthorObj
до нуля, ноAuthor()
экземпляр по-прежнему имеет 1 сильную ссылкуauthorObj.book.author
1 ответ
Так вы, ребята, можете объяснить для меня, что между ними? а также! в authorObj!.book?.author = authorObj и authorObj!.book!.author = authorObj?
Когда вы используете ?
чтобы развернуть необязательное, это называется необязательным созданием цепочки. Если необязательный nil
результат всей цепочки будет nil
, Преимущество использования ?
является то, что ваше приложение не будет зависать, если развернутое значение nil
,
Так:
authorObj!.book?.author = authorObj
потерпит крах, если authorObj
является nil
(из-за принудительной развертки !
).
а также:
authorObj!.book!.author = authorObj
потерпит крах, если либо authorObj
или же book
является nil
,
Безопасный способ написать это будет:
authorObj?.book?.author = authorObj
Если authorObj
или же book
является nil
, это ничего не будет делать, и он не потерпит крах.
authorObj - это сильная ссылка, такая же как и authorObj.book.author, это тоже сильная ссылка? Потому что он не имеет слабых или неподготовленных до вар.
Имеет смысл говорить об одной переменной, когда речь идет о слабых и сильных. Нет смысла спрашивать, authorObj.book
слабый; Вы можете сказать, что Author
содержит слабую ссылку на book
,
Только authorObj.book является слабой ссылкой. Но когда я назначаю authorObj для nil, все деинициализируются. Зачем? Я назначаю только authorObj для nil, но экземпляр Author() все еще имеет 1 сильную ссылку authorObj.book.author
Когда вы назначаете nil
в authorObj
это была последняя сильная ссылка на authorObj
Таким образом, автоматический подсчет ссылок (ARC) уменьшает счетчик ссылок, а затем освобождает все ссылки внутри authorObj
, Если это сильные ссылки, это уменьшает счетчик ссылок, и если это была последняя ссылка на этот объект, объект также освобождается. Если какой-либо другой объект содержит слабую ссылку на какой-либо освобожденный объект, ARC установит для этого значения значение nil
во всех слабых указателей.
Чтобы проверить это на игровой площадке, поместите ваши команды в функцию под названием test
и добавить print
заявления, чтобы вы могли видеть, когда все происходит.
class Author {
weak var book: Book?
deinit {
print("Dealloc Author")
}
}
class Book {
var author: Author?
deinit {
print("Dealloc Book")
}
}
func test() {
print("one")
var authorObj: Author? = Author()
print("two")
authorObj!.book = Book()
print("three")
authorObj!.book?.author = authorObj
print("four")
}
test()
Выход:
one two Dealloc Book three four Dealloc Author
Стоит отметить, что Book
освобождается перед шагом three
, Зачем? Потому что на это нет сильных указателей. Вы выделили его, а затем присвоили единственную ссылку на него слабому указателю внутри Author, поэтому ARC немедленно освободил его.
Это объясняет, почему authorObj!.book!.author = authorObj
падает, потому что authorObj!.book
является nil
так как Book
который был только назначен, был освобожден.
Теперь попробуйте назначить Book()
в локальную переменную book
:
func test() {
print("one")
var authorObj: Author? = Author()
print("two")
let book = Book()
authorObj!.book = book
print("three")
authorObj!.book?.author = authorObj
print("four")
authorObj = nil
print("five")
}
test()
На этот раз вывод совсем другой:
one two three four five Dealloc Book Dealloc Author
Теперь локальная переменная book
держит сильную ссылку на Book
это было выделено, поэтому оно не освобождается сразу.
Обратите внимание, хотя мы назначены nil
в authorObj
в ногу four
не было освобождено до book
был освобожден после шага five
,
Локальная переменная book
держит сильную ссылку на Book()
, а также Book
держит сильную ссылку на Author
поэтому, когда мы назначаем nil
в authorObj
в ногу four
, authorObj
не может быть освобожден, потому что book
все еще держит сильную ссылку на это. когда test
заканчивается, локальная переменная book
освобождается, поэтому сильная ссылка на authorObj
освобождается, и, наконец, authorObj
может быть освобожден, так как последняя сильная ссылка на него исчезла.