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

  • Только authorObj.book - слабая ссылка. Но когда я присваиваю authorObj значение nil, все деинициализируются. Почему? Я присваиваю nil только authorObj, но экземпляр Author() по-прежнему имеет 1 сильную ссылку authorObj.book.author


person Hung Nguyen    schedule 19.06.2016    source источник
comment
считается лучшей практикой вставлять код непосредственно в вопрос, а не давать ссылку на картинку   -  person Andrey Chernukha    schedule 19.06.2016
comment
Возможный дубликат Что означает восклицательный знак в Swift язык?   -  person FredericP    schedule 19.06.2016
comment
Добро пожаловать в Stack Overflow @HungNguyen. Я отредактировал ваш вопрос, чтобы разместить фактический код вместо изображения. Пожалуйста, опубликуйте свой реальный код в будущем, так как это позволит другим легче опробовать ваш код. Если мой ответ решит вашу проблему, примите его, нажав на галочку рядом с ним, чтобы он стал зеленым. meta.stackexchange. ru / questions / 5234 /   -  person vacawama    schedule 19.06.2016
comment
@vacawama, спасибо! Я понял. Извините за мою вину.   -  person Hung Nguyen    schedule 19.06.2016


Ответы (1)


Так вы можете объяснить мне, в чем разница между ними? а также ! в authorObj! .book? .author = authorObj и authorObj! .book! .author = authorObj?

Когда вы используете ? для разворачивания необязательного объекта, это называется необязательной цепочкой. Если необязательный параметр nil, результатом всей цепочки будет nil. Преимущество использования ? заключается в том, что ваше приложение не выйдет из строя, если разворачиваемое значение равно nil.

So:

authorObj!.book?.author = authorObj

произойдет сбой, если authorObj равно nil (из-за принудительного развертывания !).

а также:

authorObj!.book!.author = authorObj

произойдет сбой, если authorObj или book равно nil.

Безопасный способ написать это:

authorObj?.book?.author = authorObj

Если authorObj или book равно nil, ничего не будет и не произойдет сбой.

authorObj - это сильная ссылка, такая же, как и authorObj.book.author, это тоже сильная ссылка? Потому что у него нет weak или unowned до var.

Когда речь идет о слабом и сильном, имеет смысл говорить только об одной переменной. Нет смысла спрашивать, является ли authorObj.book слабым; можно сказать, что Author содержит слабую ссылку на book.

Только authorObj.book - слабая ссылка. Но когда я присваиваю authorObj значение nil, все деинициализируются. Почему? Я присваиваю nil только authorObj, но экземпляр 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. Почему? Потому что на него нет сильных указателей. Вы выделили его, а затем назначили единственную ссылку на него weak указателю внутри 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 может быть освобожден, поскольку последняя сильная ссылка на нее исчезла.

person vacawama    schedule 19.06.2016
comment
Большое спасибо! Я понял! - person Hung Nguyen; 19.06.2016