Error when returning [anArray count] in numberOfRowsInComponent in UIPickerView
I have a UIViewController that has a UIPickerView and UITableView. The UIPicker has 3 components.
When I try to define the number of components in each array by returning [anArray count], the program freezes without throwing an error when loading the UIViewController.
When I put NSLogs in viewDidLoad:
for [self.hours count]
, [self.minutes count]
, and [self.meridiem count]
, the correct number of values are returned.
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray *tempHours = [NSMutableArray array];
for (NSInteger i = 0; i < 12; i++) [tempHours addObject:[NSNumber numberWithInteger:(i+1)]];
self.hours = [NSArray array];
hours = tempHours;
[tempHours release];
NSMutableArray *tempMinutes = [NSMutableArray array];
for (NSInteger i = 0; i <= 59; i++) [tempMinutes addObject:[NSNumber numberWithInteger:i]];
self.minutes = [NSArray array];
minutes = tempMinutes;
[tempMinutes release];
NSMutableArray *tempMeridiem = [NSMutableArray array];
for (NSInteger i = 0; i <= 1; i++) [tempMeridiem addObject:[NSNumber numberWithInteger:i]];
self.meridiem = [NSArray array];
meridiem = tempMeridiem;
[tempMeridiem release];
}
Now, in pickerView:numberOfRowsInComponent:Component:
, the code freezes without an error if I try to output [anArray count]
(where anArray is a placeholder for hours, minutes, and meridiem). If I set numberOfRows to an integer value, or to component+1
everything works just fine.
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
NSInteger numberOfRows;
if (component == 0) {
// numberOfRows = component+1;
numberOfRows = [self.hours count];
}
else if(component == 1) {
// numberOfRows = component+1;
numberOfRows = [self.minutes count];
}
else {
// numberOfRows = component+1;
numberOfRows = [self.meridiem count];
}
return numberOfRows;
}
I have a feeling my NSArrays (hours, minutes, meridiem) aren't being retained, but running the Analyzer doesn't show me that I have any memory le开发者_开发百科aks in that ViewController.
Any and all help would be greatly appreciated!
You are creating unnecessary arrays and not retaining the ones that count. See your code:
self.hours = [NSArray array];
hours = tempHours;
[tempHours release];
Here you created an autoreleased array and set it to your self.hours property (which hopefully has a retain
keyword attached to it). But then the very next line you access the ivar directly and set it to tempHours
. Then you send a release message to tempHours
without having ever retained it. Since tempHours is autoreleased it will magically disappear on the next drain of the auto release pool. I believe what you wanted to do is:
self.hours = tempHours;
Ditto for your other array collections.
These lines are wrong:
self.hours = [NSArray array];
hours = tempHours;
you should just use
self.hours = tempHours;
What was happening in your original code was:
self.hours
is set to an array created by[NSArray array]
. Call ita
.a
is correctly retained.now,
hours
is set totempHours
. This directly accesses the ivar, without using the setter. So, it doesn't retaintempHours
.a
is lost without being correctly released, too.tempHours
is released. It's not retained by anybody, so it's dealloc'ed, too.
So, don't do that. You'd like to read the memory management guide. I can't believe the Analyzer (below the Build command) didn't catch this mistake... maybe you'd like to file a bug toward the LLVM team about this case.
The problem was not in the ViewController I was trying to display. I just copied the interface and implementation files into a new proejct, and once I compiled it, everything worked like a dream.
The problem is with the RootViewController of my project that modally invokes the controller with the UIPickerView. Apparently, I have a memory leak in there. Should be trivial to fix.
Thanks everyone for your help!
精彩评论