encountering numerous leaks on iphone device when using NSOperationQueue and trying to change sliders / pickers etc.
I am able to change labels without an issue, but if I try to change a slider or picker both created on interface builder I get these leaks.
Leaked Object # Address Size Responsible Library Responsible Frame
GeneralBlock-16 0x1b00a0 16 GraphicsServices GetFontNames
GeneralBlock-16 0x1aea90 16 WebCore WebThreadCurrentContext
GeneralBlock-16 0x1aea80 16 GraphicsServices GSFontGetFamilyName
GeneralBlock-64 0x1a7370 64 UIKit GetContextStack
code below
- (void)loadData {
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(firstRun)
object:nil];
[queue_ addOperation:operation];
[operation release];
}
- (void)firstRun {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
[self setSliders];
NSLog(@"firstRun method end");
[pool drain];
}
- (void)setSliders {
NSMutableArray *tempArray = [[[NSMutableArray alloc]init] autorelease];
aquaplannerAppDelegate *appDelegate = (aquaplannerAppDelegate *)[[UIApplication sharedApplication] delegate];
tempArray = appDelegate.settingsValuesArray;
freshMarineSegment.selectedSegmentIndex = [[tempArray objectAtIndex:0]intValue];
for (int i = 1; i <= 20; i++ ) {
UILabel *label = (UILabel *)[self.view viewWithTag:200+i]; // gets label based on tag
UISlider *slider = (UISlider *)[self.view viewWithTag:100+i]; // gets slider based on tag
slider.value = [[tempArray objectAtIndex:i]intValue];
label.text = [[[NSString alloc] initWithFormat:@"%@",[tempArray objectAtIndex:i]] autorelease];
[label release];
[slider release];
}
}
I'm assuming you're doing something else before setSliders
for which you created the NSOperation, and you just omitted that code.
UIKit is not guaranteed to be thread safe, and you should only access your interface elements on the main thread. This is mentioned in a few places in the docs, but the most telling is in the Cocoa Fundamentals Guide:
All UIKit objects should be used on the main thread only.
So firstRun
should look more like this:
- (void)firstRun {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
// Do something important here...
[self performSelectorOnMainThread:@selector(setSliders) withObject:nil waitUntilDone:NO];
NSLog(@"firstRun method end");
[pool drain];
}
Why are you using an NSMutableArray
in setSliders
? You're never actually changing the array, and mutable data structures can wreak havoc in threaded programming.
Also, I'd rename the setSliders
method to something like updateSliders
. It's a Cocoa style issue. Methods that start with "set" should be used for mutating a single instance variable/property.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With