First, BLOCK circular reference
Typically, a class uses block as its own property variable, and the class itself is used in the block's method body. form a circular reference.
When a block is defined, a copy is made to the external variable, a strong reference, and self as a strong reference.
The solution is as follows:
1 #import "ViewController.h"2 #import "NetworkTools.h"3 4 @interfaceViewcontroller ()5@property (nonatomic, strong) Networktools *tools;6 @end7 8 @implementationViewcontroller9 //1. To remove the circular reference, you need to pay attention to interrupt the reference chain! Ten- (void) Viewdidload { One [Super Viewdidload]; A - //Local variables do not produce circular applications, and global properties produce circular references -Self.tools =[[Networktools alloc] init]; the - //1. When a block is defined, a copy of the external variable is made and a strong reference is made to self - - //To dismiss a circular reference Method 1 + //__weak is available in IOS 5.0 - //If the asynchronous operation is not complete, release the controller, __weak itself is a weak reference + //when the asynchronous execution is complete, the callback is made, self is freed, the property cannot be accessed, and the method cannot be called A //__weak is equivalent to weak and does not make a strong reference, but if the object is freed, the address that is executed will point to nil at //__weak More secure -__weaktypeof(self) weakself =Self ; - - //To dismiss a circular reference method 2 - //__unsafe_unretained is available in IOS 4.0 - //MRC Classic error, Exc_bad_access bad memory access, wild pointer in //equivalent to assign, does not make a strong reference, but if the object is freed, the memory address remains the same, if called again, there will be wild pointer access - //__unsafe_unretained typeof (self) weakself = self; to +[Self.tools loaddata:^ (NSString *html) { - //strongself Strong reference, strong reference to Weakself, intent, want to continue executing callback code after asynchronous completion the //but it doesn't work!!!!!!!! *__strongtypeof(self) strongself =weakself; $ Panax NotoginsengNSLog (@"%@ %@", HTML, strongself.view); - }]; the } + A- (void) Dealloc { theNSLog (@"Controller"); + } - $ @end
Second, timer Nstimer Circular Reference
Mainly because from the point of view of the timer, the timer thinks that the caller self is being refactored into Dealloc, and in Dealloc can stop the timer's timing and free up memory, but from the perspective of self, he thinks that the timer does not stop the timing and does not deconstruct, Then I never got a chance to get into dealloc. Circular references, waiting for each other, the descendants of the endless also.
Example Description:
On the one hand, Nstimer is often used as a member variable for a class, while Nstimer is initialized to specify self as target, which can easily cause circular references. On the other hand, if the timer is always in the validate state, its reference count will always be greater than 0. Let's look at an example of Nstimer use (ARC mode):
1Import <Foundation/Foundation.h>2 3 InterfaceFriend:nsobject4-(void) Cleantimer;5 End6 7Import"Friend.h"8 9 InterfaceFriend ()TenStimer *_timer; One End A - implementation Friend - the-(ID) Init - { - if(self =[Super Init]) { -_timer = [Nstimer scheduledtimerwithtimeinterval:1target:self selector: @selector (handletimer:) + Userinfo:nil Repeats:yes]; - } + returnSelf ; A } at -- (void) Handletimer: (ID) Sender - { -NSLog (@"%@ say:hi!", [Selfclass]); - } - in- (void) Cleantimer - { to [_timer invalidate]; +_timer =Nil; - } the *- (void) Dealloc $ {Panax Notoginseng [self cleantimer]; -NSLog (@"[Friend class] is dealloced"); the } + A @end
Initializes a friend object outside the class and releases the friend after 5 seconds of delay (externally running in a non-arc environment)
1 friend *f = [[Friend alloc] init]; 2 5*nsec_per_sec), Dispatch_get_main_queue (), ^{3 [f release]; 4 });
The result we expect is that after 5 seconds of initialization, the F object is called by the Dealloc method of the Release,f, and in Dealloc the timer expires and the object is refactored. But the result is this:
1 --Geneva- - -:xx:35.300wzlcodelibrary[41422:3390529] Friend say:hi!2 --Geneva- - -:xx:36.299wzlcodelibrary[41422:3390529] Friend say:hi!3 --Geneva- - -:xx:37.300wzlcodelibrary[41422:3390529] Friend say:hi!4 --Geneva- - -:xx:38.299wzlcodelibrary[41422:3390529] Friend say:hi!5 --Geneva- - -:xx:39.299wzlcodelibrary[41422:3390529] Friend say:hi!//after running 5 times, it didn't stop as expected.6 --Geneva- - -:xx:40.299wzlcodelibrary[41422:3390529] Friend say:hi!7 --Geneva- - -:xx:41.300wzlcodelibrary[41422:3390529] Friend say:hi!8 --Geneva- - -:xx:42.300wzlcodelibrary[41422:3390529] Friend say:hi!9 --Geneva- - -:xx:43.299wzlcodelibrary[41422:3390529] Friend say:hi!Ten --Geneva- - -:xx:44.300wzlcodelibrary[41422:3390529Friend Say:hi!<br>, ... Can't stop at all .....
What is this for? Mainly because from the point of view of the timer, the timer thinks that the caller (Friend object) will enter the Dealloc when it is refactored, and in Dealloc can stop the timer's timing and release the memory, but from friend's point of view, he thinks that the timer does not stop the timing, Then I never got a chance to get into dealloc. Circular references, waiting for each other, the descendants of the endless also. The crux of the problem is that-(void) The invocation of the Cleantimer function is not opportune, and obviously cannot be placed in the caller's dealloc. A good solution is to open this function and let friend's caller explicitly invoke it to clean up the scene. As follows:
1 friend *f = [[Friend alloc] init]; 2 5*nsec_per_sec), Dispatch_get_main_queue (), ^{3 [f Cleantimer]; 4 [F release]; 5 });
Third, entrusted delegate
There is a circular reference issue on the delegation issue is a cliché, this article is no longer detailed, to avoid the problem of the killer is also simple to cry, a word tactic: declare delegate when you use assign (MRC) or weak (ARC), do not hand the cheap play retain or strong, After all, this basically can't escape the circular reference!
It is said that we are common, in fact, circular reference means that our strong reference to form a closed loop, there will be a lot of their own code will appear in writing, usually still pay attention to the wording.
Sorry, the following again verbose, further explained:
circular references, when multiple objects are referenced to each other, make the reference a ring that causes the outer ring memory to not really fall off. Actually a bit like a deadlock. For example: A->b->c->....->x->b, which refers to a strong reference, so that the reference count of B is 2, if A is released by the system, theoretically a will automatically reduce the resource referenced by a, that is, B, then the reference count of B becomes 1 , all B cannot be freed, but a has been released, and all B's memory parts are definitely no longer able to release and re-use this portion of memory space, causing a memory leak. situation One: Delegate Delegate is the most commonly encountered circular reference in development in iOS, typically using a weak reference weak or Assign@property (nonatomic, weak, nullable) when declaring delegate<uitableviewdelegate>delegate, of course, how to choose to use assign or WEAK,MRC words can only use assign, in the case of arc is best to use weak, because the weak modified variable after the automatic to point to nil, to prevent unsafe wild pointer exists Case TWO: Blockblock is also a more common circular reference problem, the use of self in block is prone to circular references, so many people in the use of block, when the addition of useful to self will declare a __weak to decorate self. In fact, this is not the case, not all use block will have a self circular reference problem, only self has a strong reference block to this situation. Therefore, the general use of block in the function temporarily does not appear in the loop application, because this time the block reference is the stack. When the block on the stack is released, the reference count of self in the block will also be lost. Of course, you do not have to self to the block has a direct reference to appear, if self variable b,b has a block variable, it is prone to this situation, the good is in the block has a circular reference, Xcode7 a warning prompt (previous version is not deterministic) appears. situation Three: Nstimer This is a magical nstimer, when you create a use Nstimer, Nstimer will default to the current self has a strong reference, all when the self uses the completion of the plan, Be sure to use Nstimer's invalidate to stop the time control reference to self [_timer invalidate];
IOS Circular Reference Solution