In ios development, the ARC mode is enabled and the system automatically manages the memory. If block is used in the program, pay attention to the memory leakage caused by circular reference.
I have encountered a problem over the past few days. When a normal page is dismiss, I want to call the dealloc method, but my program does not call it. After studying it for a long time, I finally found out where the problem is.
The initial code is as follows:
-(Void) getMyrelatedShops
{
[Self. loadTimer invalidate];
Self. loadTimer = [NSTimer scheduledTimerWithTimeInterval: 0.1
Target: discoverView
Selector: @ selector (loadWaiting)
UserInfo: nil
Repeats: YES];
SendedRequest = [[findsdomainservice sharedInstance] getMyRelatedShopsWithPageNO: pageNo
SuccessBlock: ^ (TMRequest * request ){
[Self. loadTimer invalidate];
[Self shopListRequestFinished: request];
} FailedBlock: ^ (TMRequest * failedRequest ){
[Self. loadTimer invalidate];
[Self shopListRequestFailed: failedRequest];
}];
}
The Code does not seem to have any problems on the surface, but further research will find two problems.
1. self is referenced in the block. self is block retain. sendedRequest retain another copy of the block.
2. sendedRequest defines the value assignment in the self class, so it is retain by self.
Therefore, it forms a circular reference and does not call dealloc.
Another problem is that as long as the repetitive timer has not been invalidated, the target object will be held and not released. Therefore, when you use self as the target, you cannot expect invalidate timer in dealloc, because dealloc will never be called before the timer is not invalidate. Therefore, you need to find a suitable time and place for invalidate timer, but it is not in dealloc.
Modify as follows:
-(Void) getMyrelatedShops
{
[Self. loadTimer invalidate];
Self. loadTimer = [NSTimer scheduledTimerWithTimeInterval: 0.1
Target: discoverView
Selector: @ selector (loadWaiting)
UserInfo: nil
Repeats: YES];
_ Unsafe_unretained FindShopVC * wfindShopVC = self;
SendedRequest = [[findsdomainservice sharedInstance] getMyRelatedShopsWithPageNO: pageNo
SuccessBlock: ^ (TMRequest * request ){
[WfindShopVC. loadTimer invalidate];
[WfindShopVC shopListRequestFinished: request];
} FailedBlock: ^ (TMRequest * failedRequest ){
[WfindShopVC. loadTimer invalidate];
[WfindShopVC shopListRequestFailed: failedRequest];
}];
}
In this way, loop reference is avoided, and the dealloc method will be called when the page is logged out.