2013-01-17 40 views
0

我想使用故事板和JSON创建一个松散版本的LazyTabelImages。在我的主TableViewController的ViewDidLoad中,我启动一个NSURLConnection来获取JSON数据,但是我的单元格在连接完成之后才加载。我希望LazyTableImages具有相同的行为,其中单元格加载为空白,但是然后填充信息(重新加载表格数据)。如果我不使用storyboard,我可以复制它,因为LazyTables不使用storyboard,但这不是一个选项。iPhone - 使UITableViewCells出现在NSURLConnection完成之前的视图加载

我已经浏览了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]; 
} 
+0

您是否在主线程上调用网络?如果那样的话,联网块UI线程。 – jessex

+0

我已经尝试使用GCD将它从主线程移出,但之后我只是得到一个白色的屏幕,因为表永远不会加载。 NURLConnection中有一个GCD调用,用于处理不同线程上的JSON解析。 – Siriss

+0

请注意,您的NSURLConnection(应该)已经是异步的。将它移动到后台线程可能是一个糟糕的主意。正如Quinn所说,网络关注“线程是邪恶的”。 – jemmons

回答

1

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

+0

完美工作,正是我一直在寻找的。谢谢! – Siriss

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已经连接到的代码!希望能帮助到你!

+0

谢谢。我认为这是我一直需要的方法,但我仍然无法实现它的工作。我添加了代码以帮助消除混淆。 – Siriss

+0

所以我尝试过这种方式,我只是在派遣电话中挂断电话。现在我已经发布了一些代码的任何其他建议?谢谢 – Siriss

+0

小心!在线程上进行联网几乎总是一个错误。 – jemmons

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 

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

+0

感谢您的回答。我添加了代码以帮助消除任何混淆。它只花了一段时间才得到我需要的东西并正确编辑。 – Siriss

+0

我以这种方式疲倦了,但现在我做的方式是处理我最初的JSON调用的最佳方式。我在第二个类中获取图像,这只是为了获得包含URLS的JSON的第一部分,以便稍后异步获取图像。任何其他想法?谢谢 – Siriss

+0

加载JSON异步是一样的。只需要将下载的JSON数据解析为对象,而不是'-decodingDowloadedDataIntoAnImage'。而不是使用图像作为委托,您可以使用(大概)您的表的控制器,以便它可以使用新的JSON数据重新加载表。 – jemmons

相关问题