How to avoid circular references in block

Source: Internet
Author: User

Using Weak–strong Dance Technology

Block can refer to self directly, but be very careful to refer to self in the block. Because self is referenced at block, it can cause circular references. As shown in the following example:

[OBJC]View Plaincopy
  1. @interface Ksviewcontroller ()
  2. {
  3. ID _observer;
  4. }
  5. @end
  6. @implementation Ksviewcontroller
  7. -(void) Viewdidload
  8. {
  9. [Super Viewdidload];
  10. additional setup after loading the view, typically from a nib.
  11. Kstester * tester = [[Kstester alloc] init];
  12. [Tester Run];
  13. _observer = [[Nsnotificationcenter Defaultcenter]
  14. addobserverforname:@ "Testnotificationkey"
  15. Object: Nil queue: nil usingblock:^ (nsnotification *n) {
  16. NSLog (@ "%@", self );
  17. }];
  18. }
  19. -(void) Dealloc
  20. {
  21. if (_observer) {
  22. [[Nsnotificationcenter Defaultcenter] removeobserver:_observer];
  23. }
  24. }


In the code above, we add an observer to the notification hub and then release the registration at Dealloc, and everything looks normal. But here are two questions:
1.) In the message notification block referenced to self, where the Self object is block retain, and _observer retain a copy of the block, Notification Center and hold _observer. So as long as the _observer object has not been de-registered, the block will be held by the Notification center, so that self will not be freed and its dealloc will not be invoked. And we expect to removeobserver in Dealloc to remove the notification center from the _observer/block retain.
2.) At the same time, _observer is defined as an assignment in the Self's class, and therefore is self retain, thus forming a circular reference.
The above procedure 1) deserves an in-depth analysis:
The block variables in AddObserverForName:object:queue:usingBlock: In Apple's official document are described below:

The block is copied by the Notification center and (the copy) held until the observer registration is removed.
Therefore, the notification center copies the block and holds the copy until the _observer registration is released. In ARC, the block will retain self, either directly referencing self or by referencing the member variable of self, in the block being copied.
These two problems can be solved with Weak–strong dance technology. This technique was introduced in the WWDC: WWDC Session #322 (objective-c advancements in Depth)

[OBJC]View Plaincopy
  1. __weak Ksviewcontroller * wself = self ;
  2. _observer = [[Nsnotificationcenter Defaultcenter]
  3. addobserverforname:@ "Testnotificationkey"
  4. Object: Nil queue: nil usingblock:^ (nsnotification *n) {
  5. Ksviewcontroller * sself = wself;
  6. if (sself) {
  7. NSLog (@ "%@", sself);
  8. }
  9. else {
  10. NSLog (@ "<self> Dealloc before we could run this code.");
  11. }
  12. }];

Let's analyze why this technique works.
First, a weak reference to self is defined before the block wself, because it is a weak reference, so wself becomes nil when Self is freed, and then references the weak application in the block, taking into account the multithreaded case, by referencing the weak reference by using the strong reference self. If self is not nil at this point, self is retain to prevent self from being freed during subsequent use, and then the strong reference self is used in subsequent block blocks, noting that the self is nil detected before use because of the weak reference ws in a multithreaded environment When the elf assigns a strong reference to a sself, the weak reference wself may already be nil.
In this way, the block does not hold the self reference, thus breaking the circular reference

How to avoid circular references in block

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.