iPhone - 在NSURLConnection完成之前,使UITableViewCells出现在视图加载中

时间:2013-01-17 02:44:44

标签: iphone uitableview nsurlconnection

我正在尝试使用storyboard和JSON创建一个松散版本的LazyTabelImages。在我的主TableViewController上的ViewDidLoad中,我启动一个NSURLConnection来获取JSON数据,但是我的单元格在连接完成之后才会加载。我想要与LazyTableImages具有相同的行为,其中单元格作为空白加载,但随后填写信息(重新加载表格数据)。如果我不使用故事板,我可以复制这个,因为LazyTables不使用故事板,但这不是一个选项。

我已经浏览了LazyTableImages以尝试找到解决方案,但故事板对我来说有很大的不同(无论如何)。

是否有一种简单的方法可以将单元格作为空白加载?例如,如果设备没有互联网,我仍然希望我的TableView出现,我将在单元格中放置一条自定义消息。

代码:

我的viewDidLoad中我初始化连接的部分....

NSURLRequest *urlrequest = [NSURLRequest requestWithURL:[NSURL URLWithString:serverURL]];
    self.dataConnection = [[NSURLConnection alloc] initWithRequest:urlrequest delegate:self];

    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;

... connectionDidFinnishLoading

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    //ListData below is an array that my data received (JSON) is loaded into. It is then passed to getTableData.
    self.dataConnection = nil;
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self performSelectorOnMainThread:@selector(getTableData:) withObject:ListData waitUntilDone:YES];
    });
}

... getTableData

-(void)getTableData:(NSData *)jsonData
{
    NSError *error = nil;
    arrayEntries = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableLeaves error:&error];
    for (int x = 0; x < arrayEntries.count; x++)
    {
        NSMutableDictionary *dic = [arrayEntries objectAtIndex:x];

        //ARecord is a class just like in LazyTableImages that creates objects to keep the icons/data together. The ARecords are loaded into the TableView
        ARecord *arecord = [[ARecord alloc] init];

        NSString *title = [dic objectForKey:@"title"];
        NSString *subt = [dic objectForKey:@"subtitle"];
        NSString *url = [dic objectForKey:@"image_URL"];
        arecord.Icon = nil;
        arecord.URL = url;
        arecord.Name = title;
        arecord.title = subt;

        //this is where I load an array full of the arecord objects.
        [array addObject:arecord];
    }
    [self.tableView reloadData];
}

3 个答案:

答案 0 :(得分:1)

我用两个对象做这个。首先,我有一个图像提取器类,它可以异步下载数据,并在代理完成时通知代理。然后我有一个图像视图类,实现了fetcher的委托方法。如下所示:

@implementation AsyncImageFetcher
-(id)initWithURL:(NSURL *)aURL andDelegate:(id<SomeProtocol>)aDelegate{

  //...

  NSURLRequest *req = [NSURLRequest requestWithURL:aURL];
  //Note that NSURLConnection retains its delegate until the connection
  //terminates! See comments in MyImageView below.
  [NSURLConnection connectionWithRequest:req delegate:self];

  //...
}

//Implement standard connection delegates here. The important part is:
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{

  // ...

  UIImage *anImage = [self decodeDownloadedDataIntoAnImage];
  if([[self delegate] respondsToSelector:@selector(imageFetcher:didFetchImage:)]){
    [[self delegate] imageFetcher:self didFetchImage:anImage];
  }

  //...
}

@end

然后我继承UIImageViewUIView或其他东西(取决于你需要多么灵活)来实现委托协议并启动抓取器:

@implementation MyImageView

-(id)initWithURL:(NSURL *)aURL andPlaceHolderImage:(UIImage *)aPlaceHolder{

  //...

  [self setImage:aPlaceHolder];

  //Note we don't assign this to an ivar or retain it or anything. 
  //That's ok because the NSURLConnection inside the fetcher actually 
  //retains the fetcher itself. So it will live until the connection 
  //terminates -- which is exactly what we want. Thus we disable 
  //CLANG's noisy warnings.
  #pragma clang diagnostic push
  #pragma clang diagnostic ignored "-Wunused-value"
  [[AsyncImageFetcher alloc] initWithURL:aURL andDelegate:self];
  #pragma clang diagnostic pop

  return self;
}


-(void)imageFetcher:(MCMAsyncImageFetcher *)anImageFetcher didFetchImage:(UIImage *)anImage{
  [self setImage:anImage];
}

@end

在您的具体情况下,您只需在MyImageView中将imageView设置为单元格-tableView:cellForRowAtIndexPath:,当然会为其占位符和网址传递合理的值。

答案 1 :(得分:1)

我做过类似的事情。在viewDidLoad中:我将表数据的数组设置为[NSNull null]的几个对象,因为我想在下载数据时显示许多空白行。在cellForRowAtIndexPath中:我检查[self.arrayOfTableData objectAtIndex:indexPath.row] = [NSNull null]。如果是,则返回“空白”单元格,否则使用ARRecrod数据加载单元格。 然后,当URL完成时,将NSNull数组替换为您的ARRecords数组。

答案 2 :(得分:0)

由于我没有看到您的代码,我只想在此提出建议:

- (void)viewDidLoad
{
    [super viewDidLoad];

    dispatch_queue_t queue = dispatch_queue_create(NULL, NULL);
    dispatch_async(queue, ^{

        //add your connection code here
        //parse the json and store the data
        //

        dispatch_async(dispatch_get_main_queue(), ^{

            //here to reload your table view again, 
            //since UI related method should run on main thread.

            [YOUR_TABLEVIEW reloadData];

        });

    });

    [YOUR_TABLEVIEW reloadData];
}

注意:确保故事板中的tableview已连接到代码中的tableview!希望它有所帮助!