samedi 27 décembre 2014

iOS ARC - Why objects not be released immediately?

Maybe this is NOT a duplicate question, as I have searched and tried many solutions about how to release objects under ARC.

The code is simple:



@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
[self recreateView];

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)];
[self.view addGestureRecognizer:tap];
}

- (void)tapped:(UITapGestureRecognizer *)g
{
[self recreateView];
}

- (void)recreateView
{
@autoreleasepool {
for (UIView *v in self.view.subviews) {
[v removeFromSuperview];
}
MyView *vv = [[MyView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:vv];
}
[self _performHeavyWork];
}

- (void)_performHeavyWork
{
int j = 0;
for (int i = 0 ; i < 100000000; ++i) {
j += random() % 7;
j = j % 18747;
}

}
@end


ViewController simply add a tap gesture recognizer whose action is to remove the old subview before adding a new one. MyView is a subclass of UIView which simply log a message when dealloced.



@implementation MyView
- (void)dealloc
{
NSLog(@"dealloc");
}
@end


The only magic is that the -_performHeavyWork is called every time a new view is created. When you keep on tapping on the screen quickly, the ViewController will be busy creating and discarding views. However, the odd thing is that all the discarded views are not dealloc immediately, but at the time you have stopped tapping for a while.

This is the profile of the process: Allocation Profile


As you can see, the memory keep growing if you keep on tapping and so many of MyView instances exist at the same time. And if you comment out [self _performHeavyWork];, everything will be back to normal. So my question is:



  1. Why do this happen?

  2. And how can I solve it?




Aucun commentaire:

Enregistrer un commentaire