我有一个段和一个表视图,我必须在表视图中重新加载它的工作,但是当我快速切换段按钮然后应用程序崩溃。
在片段上我有三个按钮,并且在他们的操作中我触发了对URL的请求并从该URL获取json(3个不同的URL分别返回10,17和8结果为json)。
我有一个自定义表格单元格,其中包含图像,我试图懒洋洋地加载这些图像。
在JSON结果中,json的每个对象都有各种键,如name,id,imageurl等。
id在整个应用程序中是唯一的,我正在尝试加载图像并根据该唯一ID将图像保存在本地内存中,以便我可以显示兑现图像,而无需在段更改时重新下载图像,因为所有三个部分的一些企业都是一样的。
这是我的完整代码
- (IBAction)segmentedControlIndexChanged {
NSString *offerRequestUrl = nil;
switch (self.mySegment.selectedSegmentIndex) {
case 0:
offerRequestUrl = @"url_one";
self.feedRequestUrl = [NSURL URLWithString:offerRequestUrl];
break;
case 1:
offerRequestUrl = @"url_two";;
self.feedRequestUrl = [NSURL URLWithString:offerRequestUrl];
break;
case 2:
offerRequestUrl = @"url_three";;
self.feedRequestUrl = [NSURL URLWithString:offerRequestUrl];
break;
default:
break;
}
[self parseJSONWithURL:self.feedRequestUrl];
}
- (void) parseJSONWithURL:(NSURL *) jsonURL
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData* data = [NSData dataWithContentsOfURL: jsonURL];
[self performSelectorOnMainThread:@selector(fetchedData:) withObject:data waitUntilDone:YES];
});
}
- (void)fetchedData:(NSData *)responseData {
//parse out the json data
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData
options:kNilOptions
error:&error];
self.feedsArray = [json objectForKey:@"result"];
[self.myTableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int count = self.feedsArray.count;
// if there's no data yet, return enough rows to fill the screen
if (count == 0)
{
return 1;
}
return count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// customize the appearance of table view cells
//
static NSString *CellIdentifier = @"MyTableCell";
static NSString *PlaceholderCellIdentifier = @"PlaceholderCell";
// add a placeholder cell while waiting on table data
int nodeCount = [self.feedsArray count];
if (nodeCount == 0 && indexPath.row == 0)
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:PlaceholderCellIdentifier];
cell.detailTextLabel.textAlignment = UITextAlignmentCenter;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.detailTextLabel.text = @"Loading . . .";
[self performSelector:@selector(checkAndDisplayAlert) withObject:self afterDelay:10.0];
return cell;
}
CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (nodeCount > 0)
{
// Configure the cell...
cell.carImageView.image = [UIImage imageNamed:@"Placeholder"]; //acts as default image
if([self.imageDict valueForKey:[NSString stringWithFormat:@"%@", self.feedsArray[indexPath.row][@"id_str"]]]==nil)
{
[NSThread detachNewThreadSelector:@selector(displayingSmallImage:) toTarget:self withObject:indexPath];
} else {
cell.carImageView.image = [self.imageDict valueForKey:[NSString stringWithFormat:@"%@", self.feedsArray[indexPath.row][@"id_str"]]];
}
cell.imageView.clipsToBounds = YES;
cell.titleLabel.text = self.feedsArray[indexPath.row][@"title_key"];
}
return cell;
}
- (void) displayingSmallImage:(NSIndexPath *)indexPath
{
NSString *imageUrl = self.feedsArray[indexPath.row][@"icon_url"];
NSURL *url = [NSURL URLWithString:imageUrl];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
if(image == nil)
{
image = [UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Placeholder"]];
}
[self.imageDict setObject:image forKey:[NSString stringWithFormat:@"%@", self.feedsArray[indexPath.row][@"id_str"]]];
[self performSelectorOnMainThread:@selector(imageReceived:) withObject:indexPath waitUntilDone:NO];
}
- (void) imageReceived:(NSIndexPath *)indexPath
{
UIImage *image = (UIImage *)[self.imageDict objectForKey: [NSString stringWithFormat:@"%@", self.feedsArray[indexPath.row][@"id_str"]]];
UIImageView *imgs = (UIImageView *)[[self.myTableView cellForRowAtIndexPath:indexPath] viewWithTag:IMG_TAG];
[imgs setImage:image];
[self.myTableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
- (void) checkAndDisplayAlert
{
if (!self.feedsArray && self.isAlertPresent == NO) {
UIAlertView *nilAlert = [[UIAlertView alloc] initWithTitle:@"Sorry!"
message:@"No result returned from server."
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[nilAlert setTag:kNilAlertTag];
self.isAlertPresent = YES;
[nilAlert show];
}
}
我要做的主要事情是
懒洋洋地下载图片
根据唯一ID
检查已下载图像的兑现图像字典并显示
如果可能的话,将这些下载的图像保存在本地内存(nsuserdefaults等)中,这样如果用户重新启动应用程序,那么图像也会存在,并且可以根据其唯一ID显示,无需再次下载。
任何帮助都将不胜感激。
答案 0 :(得分:0)
请发布错误日志,如果是数组越界异常我怀疑这两种方法
- (void)fetchedData:(NSData *)responseData & your tableViewDatasource
要查找导致此崩溃的代码行,请执行此操作。转到左侧的断点选项卡,然后单击底部的+。
然后你会得到这样的东西:
点击完成后,再次运行您的代码并告诉我们哪一行导致异常。
我理解你的问题,你为什么要从这个函数中的数组中获取URL
- (void) displayingSmallImage:(NSIndexPath *)indexPath
你可以传递Url来加载到该函数,从像这样的cellForRowAtIndex:
NSArray *argsToPass=[NSArray arrayWithObjects:indexPath,self.feedsArray[indexPath.row][@"icon_url"]];
[NSThread detachNewThreadSelector:@selector(displayingSmallImage:) toTarget:self withObject:argsToPass];
并将您的功能修改为:
- (void) displayingSmallImage:(NSArray *)args
{
if([args count] == 0)
{
NSString *imageUrl = [args objectAtIndex:1];
NSIndexPath *indexPath=[args objectAtIndex:0];
NSURL *url = [NSURL URLWithString:imageUrl];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];
if(image == nil)
{
image = [UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Placeholder"]];
}
[self.imageDict setObject:image forKey:[NSString stringWithFormat:@"%@", self.feedsArray[indexPath.row][@"id_str"]]];
[self performSelectorOnMainThread:@selector(imageReceived:) withObject:indexPath waitUntilDone:NO];
}
}
答案 1 :(得分:0)
您可以在向服务器发送请求时设置self.view.userInteractionEnabled = NO。 当你获得数据时,只需启用用户交互即可避免多个请求。