Чем отличается? а также! в слабой, сильной ссылке в 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 может быть освобожден, так как последняя сильная ссылка на него исчезла.

Другие вопросы по тегам