Shall we always use [unowned self] inside closure in Swift

前端 未结 9 1941
耶瑟儿~
耶瑟儿~ 2020-11-22 05:22

In WWDC 2014 session 403 Intermediate Swift and transcript, there was the following slide

\"enter

9条回答
  •  醉酒成梦
    2020-11-22 05:59

    Here is brilliant quotes from Apple Developer Forums described delicious details:

    unowned vs unowned(safe) vs unowned(unsafe)

    unowned(safe) is a non-owning reference that asserts on access that the object is still alive. It's sort of like a weak optional reference that's implicitly unwrapped with x! every time it's accessed. unowned(unsafe) is like __unsafe_unretained in ARC—it's a non-owning reference, but there's no runtime check that the object is still alive on access, so dangling references will reach into garbage memory. unowned is always a synonym for unowned(safe) currently, but the intent is that it will be optimized to unowned(unsafe) in -Ofast builds when runtime checks are disabled.

    unowned vs weak

    unowned actually uses a much simpler implementation than weak. Native Swift objects carry two reference counts, and unowned references bump the unowned reference count instead of the strong reference count. The object is deinitialized when its strong reference count reaches zero, but it isn't actually deallocated until the unowned reference count also hits zero. This causes the memory to be held onto slightly longer when there are unowned references, but that isn't usually a problem when unowned is used because the related objects should have near-equal lifetimes anyway, and it's much simpler and lower-overhead than the side-table based implementation used for zeroing weak references.

    Update: In modern Swift weak internally uses the same mechanism as unowned does. So this comparison is incorrect because it compares Objective-C weak with Swift unonwed.

    Reasons

    What is the purpose of keeping the memory alive after owning references reach 0? What happens if code attempts to do something with the object using an unowned reference after it is deinitialized?

    The memory is kept alive so that its retain counts are still available. This way, when someone attempts to retain a strong reference to the unowned object, the runtime can check that the strong reference count is greater than zero in order to ensure that it is safe to retain the object.

    What happens to owning or unowned references held by the object? Is their lifetime decoupled from the object when it is deinitialized or is their memory also retained until the object is deallocated after the last unowned reference is released?

    All resources owned by the object are released as soon as the object's last strong reference is released, and its deinit is run. Unowned references only keep the memory alive—aside from the header with the reference counts, its contents is junk.

    Excited, huh?

提交回复
热议问题