App crashes when i attempt to select a row while table was loading
I define my array in my AppDelegate.h like this:
NSMutableArray *myWishesArray;
.
.
@property (nonatomic, retain) NSMutableArray *myWishesArray;
In AppDelegate.m, i allocate its object like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
myWishesArray = [[NSMutableArray alloc] init];
.
.
return YES;
}
Suppose i have a function "Add Data to array", like this:
-(void)addDataToArray
{
NSMutableArray *tempArray = //Gets data from a web service
if ([tempArray count] > 0) {
[objAppDelegate.myWishesArray addObjectsFromArray:tempArray];
[self.myWishesTableView reloadData];
}
}
In viewDidLoad of MyViewController.m, I load the first set of 8 records into my array:
- (void)viewDidLoad {
[self addDataToArray]; //fetches page number 1 of the data to be fetched
}
In scrollViewDidEndDragging of MyViewController.m, i add next set of 8 records and use the same above mentioned code to add it in the objAppDelegate.myWishesArray:
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
currentPageNumber++;
[self addDataToArray]; //fetches data for next page number
}
-(void)viewWillAppear:(BOOL)animated
{
[self.myWishesTableView reloadData];
}
This is my cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyObject *myArrayObject = [objAppDelegate.myWishesArray objectAtIndex:indexPath.row];
}
Every time i try to click a row of the table which was visible in my table view, but was just at the end of being loaded, my app gets crashed with the following exception. It may be initial loading or loading more rows as a result of scrolling down the table view. Please keep in mind that when i give the table view enough time to settle and the motion stops and data is fully loaded, then i dont face any exception on clicking the loaded rows.
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSArray objectAtIndex:]: index 0 beyond bounds for empty array'
*** Call stack at first throw:
开发者_高级运维(
0 CoreFoundation 0x013a8be9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x014fd5c2 objc_exception_throw + 47
2 CoreFoundation 0x0139e80c -[__NSArrayI objectAtIndex:] + 236
3 WishHaHa 0x00004e1a -[AsyncImageView image] + 66
4 UIKit 0x0044e56b -[UIImageView setBackgroundColor:] + 101
5 UIKit 0x00549448 -[UITableViewCell _setOpaque:forSubview:] + 953
6 UIKit 0x0054951c -[UITableViewCell _setOpaque:forSubview:] + 1165
7 UIKit 0x0054951c -[UITableViewCell _setOpaque:forSubview:] + 1165
8 UIKit 0x0054472d -[UITableViewCell(UITableViewCellStatic) _updateAndCacheBackgroundColorForHighlightIgnoringSelection:] + 117
9 UIKit 0x0054c12a -[UITableViewCell showSelectedBackgroundView:animated:] + 1435
10 UIKit 0x00548ce3 -[UITableViewCell setHighlighted:animated:] + 231
11 UIKit 0x003fbd3b -[UITableView highlightRowAtIndexPath:animated:scrollPosition:] + 756
12 UIKit 0x003f78d8 -[UITableView touchesBegan:withEvent:] + 1349
13 UIKit 0x004512b8 forwardMethod2 + 92
14 UIKit 0x0054cc15 -[UITableViewCell touchesBegan:withEvent:] + 319
15 UIKit 0x004512b8 forwardMethod2 + 92
16 UIKit 0x00610987 _UIGestureRecognizerSortAndSendDelayedTouches + 3609
17 UIKit 0x006110fc _UIGestureRecognizerUpdateObserver + 927
18 CoreFoundation 0x01389fbb __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 27
19 CoreFoundation 0x0131f0e7 __CFRunLoopDoObservers + 295
20 CoreFoundation 0x012e7bd7 __CFRunLoopRun + 1575
21 CoreFoundation 0x012e7240 CFRunLoopRunSpecific + 208
22 CoreFoundation 0x012e7161 CFRunLoopRunInMode + 97
23 GraphicsServices 0x01a9d268 GSEventRunModal + 217
24 GraphicsServices 0x01a9d32d GSEventRun + 115
25 UIKit 0x0039442e UIApplicationMain + 1160
26 WishHaHa 0x00002a5c main + 102
27 WishHaHa 0x000029ed start + 53
)
terminate called after throwing an instance of 'NSException'
I have done a lot of research on my problem and found that possible causes of NSRangeException may be:
- numberOfRowsInSection:(NSInteger)section; method of the UITableView's data source is delivering wrong values.
- retain should be called on the array.
- Whenever you modify the underlying data for a table view you need to update the changes by either calling -[UITableView reloadData]; or the beginUpdates and endUpdates methods then adding or removing the correct index paths.
I dont think that my code has first issue. If there is second issue, then where should i make the call to retain myWishesArray? If there is third issue with my code, then how should i proceed to change my code?
Please let me know where i am doing anything wrong. I am stuck on this issue since really long.
Thanks
Edit:
After thorough investigation of the code, i have found the point which is causing this error. I am asynchronously downloading the images in cells of my table view, using the asyncimageview class. Let me paste some code here:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"CustomWishCell";
CustomWishCell *cell = (CustomWishCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"CustomWishCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
cell = (CustomWishCell *) currentObject;
break;
}
}
}
else
{
AsyncImageView* oldImage = (AsyncImageView*)[cell.contentView viewWithTag:999];
[oldImage removeFromSuperview];
}
if (indexPath.row<[objAppDelegate.myWishesArray count]) {
Wish *objWish = [objAppDelegate.myWishesArray objectAtIndex:indexPath.row];
NSString *test = objWish.facebookUserId;
[self.myEngine loadAsynchronousPhotoAvatarInView:objWish.facebookUserId imageView:cell.contentView];
cell.wishLabel.attributedText = [self.myEngine makeWisherNameAndContents:objWish.firstName lastName:objWish.lastName wishContents:objWish.contents];
}
return cell;
}
Now, myEngine contains the definitioin:
-(void)loadAsynchronousImageURLInView:(NSString*)imageUrl imageView:(UIView*)targetView
{
CGRect frame;
frame.size.width=45;
frame.size.height=45;
frame.origin.x=0;
frame.origin.y=0;
if (imageUrl != (id)[NSNull null] )
{
AsyncImageView* asyncImage = [[[AsyncImageView alloc]initWithFrame:frame] autorelease];
asyncImage.tag = 999;
NSURL *url = [NSURL URLWithString:imageUrl];
[asyncImage loadImageFromURL:url];
[targetView addSubview:asyncImage];
}
}
And the AsyncImageView class loads the image using NSURLConnection class. Please note that the app works all ok when i comment this line defined in cellForRowAtIndexPath method:
[self.myEngine loadAsynchronousPhotoAvatarInView:objWish.facebookUserId imageView:cell.contentView];
It does not crash when i click on any row that was loading. Please let me know how should i change my logic. I am not allowed to load the images synchronously, or show any indicator while images are downloading.
Your array with which you are loading your tableview is either not getting filled or is getting released somewhere before you tap on the tableView.
Please add the code where you release your array and Also please make sure that you are synthesizing your array in AppDelegate.
I think there is some issue with the array and not the tableView as array is getting empty.
I hope this helps.
It sounds to me as if your addDataToArray method does not manage to retrieve the data and fill the myWishesArray array before the click is handled. Are you retrieving the data from the web service asynchronously? Is there any way to retrieve all the data at once instead of retrieving it by sections?
精彩评论