简体   繁体   中英

UITableView crashes the application when scrolled

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM