之间有什么不同?和 !在 Swift 中的弱、强参考

What's different between ? and ! in weak, strong reference in 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

我还有两个问题:

So can you guys explain for me, what's different between ? and ! in authorObj!.book?.author = authorObj and authorObj!.book!.author = authorObj?

当您使用 ? 解包可选时,它被称为 可选链接 。如果可选的是 nil,整个链的结果将是 nil。使用 ? 的优点是,如果解包的值为 nil.

,您的应用程序不会崩溃

所以:

authorObj!.book?.author = authorObj

如果 authorObjnil 会崩溃(因为 强制展开 !)。

和:

authorObj!.book!.author = authorObj
如果 authorObjbooknil

将会崩溃。

安全的写法是:

authorObj?.book?.author = authorObj

如果 authorObjbooknil,这不会执行任何操作 并且 它不会崩溃。

authorObj is a strong reference same as authorObj.book.author, it's strong reference too? Because it dont have weak or unowned before var.

只有在谈论时谈论单个变量才有意义。问authorObj.book是不是没有意义;你可以说 Author 持有对 book.

weak 引用

Only authorObj.book is weak reference. But when I assign authorObj to nil, all are deinited. Why? I assign only authorObj to nil but Author() instance still have 1 strong reference authorObj.book.author

当您将 nil 分配给 authorObj 时,这是对 authorObj 的最后一个强引用,因此 自动引用计数 (ARC)递减引用计数器,然后释放 authorObj 内的所有引用。如果那些是 strong 引用,它会减少引用计数,如果这是对该对象的最后引用,该对象也会被释放。如果任何其他对象持有对任何已释放对象的 weak 引用,则 ARC 会将所有对象的值设置为 nil 指针。


要在 playground 中对此进行测试,请将您的命令放入一个名为 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 之前被释放。为什么?因为没有 strong 指向它的指针。您分配了它,然后将对它的唯一引用分配给 Author 内部的 weak 指针,所以 ARC 立即释放它。

这就解释了 authorObj!.book!.author = authorObj 崩溃的原因,因为 authorObj!.booknil,因为刚刚分配给它的 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 持有对分配的 Bookstrong 引用,因此它不会立即被释放。

注意,即使我们在步骤 four 中将 nil 分配给 authorObj,它直到 book 在步骤 [=55= 之后被释放之后才被释放].

局部变量book持有strongBook()的引用,Book持有strong 引用了 Author,所以当我们在步骤 four 中将 nil 赋值给 authorObj 时,authorObj 不能被释放,因为 book 仍然持有对它的 strong 引用。当test结束时,局部变量book被释放,所以strongauthorObj的引用被释放,最后authorObj可以被释放,因为最后一个 strong 对它的引用消失了。