Memory Management with Gesture Recognizer
A lot of my memory leaks are coming from this code that recognizes swipes. What am I doing wrong? The first line is something that I think is leaking (using Instruments). It's being shown as the responsible caller for a lot of the errors This is开发者_如何学运维 in ViewDidLoad:
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeRightAction:)];
[(UISwipeGestureRecognizer *)swipeRight setNumberOfTouchesRequired:2];
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
swipeRight.delegate = self;
[webView addGestureRecognizer:swipeRight];
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeLeftAction:)];
[(UISwipeGestureRecognizer *)swipeLeft setNumberOfTouchesRequired:2];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
swipeLeft.delegate = self;
[webView addGestureRecognizer:swipeLeft];
// Do any additional setup after loading the view from its nib.
}
One more question, what could cause a zombie here? Should I be autoreleasing?
AViewController *a = [[AViewController alloc]init];
[self.navigationController pushViewController:a animated:YES];
a.title =@"A View";
[a release];
Update 3: I ran instruments to look for bad allocations and with some intensive use I get a zombie here:
Error Message: An Objective-C message was sent to a deallocated object (zombie) at address: 0xf583270.
In instruments here's what I'm seeing. Instruments highlights this line and has 100% next to it.
AViewController *a = [[AViewController alloc]init];
you are alloc/initializing a UISwipeGestureRecognizer
(which makes it your job to release it) and not releasing it in your top piece of code, twice. you need to add a [swipeRight release];
and a [swipeLeft release];
after you have added those to your webview.
After adding the gesture to your views call a release
method on it, because the gesture is retained by the views in which you add.
Like below
[webView addGestureRecognizer:swipeRight];
[swipeRight release];
And
[webView addGestureRecognizer:swipeLeft];
[swipeLeft release];
Memory management in object-c is something that takes a bit of getting used too for sure. I personally let the operating handle everything for me. What this means is everytime I alloc something, I just give it an autorelease. The OS will handle the release for me when it needs to. The only time this is a problem is when you reuse an object in the same scope, the OS will send it too many releases and free the memory before you want it too. Here is an example
//This code will result in a memory crash
CustomObject *coolThing = [[[CustomObject alloc] init] autorelease];
[coolThing setAwesomeLevel:10];
[array addObject:coolThing];
[coolThing setAwesomeLevel:7];
[array2 addObject:coolThing];
Instead you would use
//Working code
CustomObject *coolThing = [[CustomObject alloc] init];
[coolThing setAwesomeLevel:10];
[array addObject:coolThing];
[coolThing setAwesomeLevel:7];
[array2 addObject:coolThing];
[coolThing release];
Now, to use autoreleases with your code, all you would do is add them to the allocs. This is why your code is leaking. When you add it to the webView object, it is increasing its retain account. And when you leave that scope, it has a retain account of 2, but you only ever send it one release (its retain would remain at 1, and never release the memory).
UISwipeGestureRecognizer *swipeRight = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeRightAction:)] autorelease];
[(UISwipeGestureRecognizer *)swipeRight setNumberOfTouchesRequired:2];
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
swipeRight.delegate = self;
[webView addGestureRecognizer:swipeRight];
UISwipeGestureRecognizer *swipeLeft = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeLeftAction:)] autorelease];
[(UISwipeGestureRecognizer *)swipeLeft setNumberOfTouchesRequired:2];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
swipeLeft.delegate = self;
[webView addGestureRecognizer:swipeLeft];
if you do not want to use autorelease like this, you need to simply add some releases after you add the gestures to the webView.
[swipeRight release];
[swipeLeft release]
精彩评论