I am having trouble finding the solution to the problem of my UITableView crashing my applciation when it is scrolled. I am using the following code taken from the Apple documentation:
NSDictionary *categoryArray;
- (void)viewDidLoad
{
[super viewDidLoad];
UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:@"bg_black.png"]];
self.view.backgroundColor = background;
[background release];
MyApp *myapp = [[MyApp alloc ] init];
categoryArray = [myapp getCategory];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [categoryArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
NSString *cellValue = [categoryArray objectForKey: [NSString stringWithFormat:@"%d", indexPath.row+1]];
cell.textLabel.text = cellValue;
return cell;
}
Where the NSDictionary categoryArray looks like this (retrieved from a global singleton class):
{
1 = Bars;
2 = Nightclubs;
3 = Societies;
4 = Colleges;
5 = University;
}
I'm pretty sure it is some sort of memory allocation/recycled cell, but I can't see exactly where I am going wrong.
The error Thrown:
2011-11-23 21:29:01.888 WhatsOniPhone[3759:b303] -[__NSArrayM objectForKey:]: unrecognized selector sent to instance 0x4e7a3f0
2011-11-23 21:29:01.892 WhatsOniPhone[3759:b303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM objectForKey:]: unrecognized selector sent to instance 0x4e7a3f0'
*** Call stack at first throw:
(
0 CoreFoundation 0x00dde5a9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x00f32313 objc_exception_throw + 44
2 CoreFoundation 0x00de00bb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0x00d4f966 ___forwarding___ + 966
4 CoreFoundation 0x00d4f522 _CF_forwarding_prep_0 + 50
5 WhatsOniPhone 0x0000340a -[FirstViewController tableView:cellForRowAtIndexPath:] + 314
6 UIKit 0x000a5b98 -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:withIndexPath:] + 634
7 UIKit 0x0009b4cc -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:] + 75
8 UIKit 0x000b07f7 -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow:] + 1348
9 UIKit 0x000a890c -[UITableView layoutSubviews] + 242
10 QuartzCore 0x016c8a5a -[CALayer layoutSublayers] + 181
11 QuartzCore 0x016caddc CALayerLayoutIfNeeded + 220
12 QuartzCore 0x016700b4 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 310
13 QuartzCore 0x01671294 _ZN2CA11Transaction6commitEv + 292
14 QuartzCore 0x0167146d _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 99
15 CoreFoundation 0x00dbf89b __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 27
16 CoreFoundation 0x00d546e7 __CFRunLoopDoObservers + 295
17 CoreFoundation 0x00d1d1d7 __CFRunLoopRun + 1575
18 CoreFoundation 0x00d1c840 CFRunLoopRunSpecific + 208
19 CoreFoundation 0x00d1c761 CFRunLoopRunInMode + 97
20 GraphicsServices 0x010161c4 GSEventRunModal + 217
21 GraphicsServices 0x01016289 GSEventRun + 115
22 UIKit 0x0003ec93 UIApplicationMain + 1160
23 WhatsOniPhone 0x00002759 main + 121
24 WhatsOniPhone 0x000026d5 start + 53
)
terminate called throwing an exceptionsharedlibrary apply-load-rules all
The problem here is, among other things, likely memory management related as you predicted. I believe that the problem is that categoryArray
is being deallocated, and replaced in memory by a different object, in the case of your exception, an NSArray. The fix to this would be to retain categoryArray
, because for some reason right now it is not being retained properly by your view controller. So, whenever you assign categoryArray
, do categoryArray = [... retain]
instead of categoryArray = ...
. If you are assigning categoryArray
as a property, declare the property as @property (nonatomic, retain) NSDictionary * categoryArray
.
If your view controller keeps ownership of categoryArray
as it should, it will be necessary to release it in the dealloc method as follows:
- (void)dealloc {
// if using a property
self.categoryArray = nil;
// if not using a property
[categoryArray release];
...
[super dealloc];
}
From your stack trace the isue is coming from the objectForKey method invoked on your category array.
From my understanding NSArray has no method 'objectForKey'. You may want an NSDictionary.
That stack trace is indicating that you're trying to invoke a method on a class that doesn't have that method. Specifically you'd called objectForKey
on an instance of NSArray
. Are you sure that categoryArray
is an instance of NSDictionary
and not NSArray
?
Looks like the object in categoryArray
is being deallocated before you get to use it. The memory address is then being reused for another object, which happens to be an __NSArrayM
.
You assign to your variable in viewDidLoad
.
categoryArray = [myapp getCategory];
It's not certain without seeing the contents of getCategory
, but I suspect that the return value is autoreleased. Therefore, you need to take ownership of the object in order for it to hang around past the end of the current method.
You should either be using the setter:
[self setCategoryArray:[myapp getCategory]];
or retaining the return value:
categoryArray = [[myapp getCategory] retain];
Also, you should rename that getCategory
method. By convention, methods starting with get
have a specific meaning: they take a pointer-to-pointer as argument and put a value into that location for the caller's use. See, eg, -[NSArray getObjects:range:]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.