UISegment之间快速切换的应用程序崩溃

时间:2013-06-20 04:12:46

标签: iphone ios objective-c ios5 ios6

我有一个段和一个表视图,我必须在表视图中重新加载它的工作,但是当我快速切换段按钮然后应用程序崩溃。

在片段上我有三个按钮,并且在他们的操作中我触发了对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];
}
 }

我要做的主要事情是

  1. 懒洋洋地下载图片

  2. 根据唯一ID

  3. 将图像缓存在本地内存中
  4. 检查已下载图像的兑现图像字典并显示

  5. 如果可能的话,将这些下载的图像保存在本地内存(nsuserdefaults等)中,这样如果用户重新启动应用程序,那么图像也会存在,并且可以根据其唯一ID显示,无需再次下载。

  6. 任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:0)

请发布错误日志,如果是数组越界异常我怀疑这两种方法

- (void)fetchedData:(NSData *)responseData & your tableViewDatasource

要查找导致此崩溃的代码行,请执行此操作。转到左侧的断点选项卡,然后单击底部的+。

enter image description here

然后你会得到这样的东西:

enter image description here

点击完成后,再次运行您的代码并告诉我们哪一行导致异常。

我理解你的问题,你为什么要从这个函数中的数组中获取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。 当你获得数据时,只需启用用户交互即可避免多个请求。