ios:将新数据加载到UICollectionView中 [英] ios: load new data into UICollectionView
问题描述
我想创建一个将图像显示到UICollectionView的应用程序。
I want to make a application which will display images into UICollectionView.
- 图像将从服务器下载,然后显示到collectionView中。
- 我在xib文件中使用自定义collectionView布局。
- 每次从服务器接收20张图片。
问题:我无法将新下载的图像显示到collectionView中。
Problem: I can't show newly downloaded images into collectionView.
这是我的代码:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
BOOL reloaded = NO;
static NSString *cellIdentifier = @"cvCell";
CVCell *cell = (CVCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
NSMutableArray *data = [self.dataArray objectAtIndex:indexPath.section];
NSString *cellData = [data objectAtIndex:indexPath.row];
dispatch_queue_t queue = dispatch_queue_create("com.justTest.anotherSingleApplication", NULL);
dispatch_async(queue, ^{
//code to be executed in the background
NSString *imageName1 = [[NSString alloc]initWithFormat:@"http://www.abc.com/images/thumb/%@", cellData];
NSString *url_Img1 = imageName1;
UIImage *aImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:url_Img1]]];
dispatch_async(dispatch_get_main_queue(), ^{
//code to be executed on the main thread when background task is finished
[cell.cellImage setImage:aImage];
});
});
if (indexPath.row == self.imageArray.count - 1 && !reloaded) {
getOnScrollImages *getImage = [[getOnScrollImages alloc] init]; // class to get image name from server
NSMutableArray *astring = (NSMutableArray *)[getImage getImageNameFromServer:@"list" board:@"111" pin:@"122345"]; // method to get image name from server
[self setNewTestArray:astring]; //adding newly downloaded image name into array
reloaded = YES;
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
});
}
return cell;
}
有任何建议吗?
注意:我刚刚开始开发iOS应用程序,这可能是一个非常愚蠢的问题。
NOTE: I am just starting developing iOS application, this may be a very silly question.
推荐答案
使用异步提取到从服务器获取数据并将其显示在collectionView中
Use asynchronously fetch to get data from server and display it in collectionView
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
YourDataModel *model = self.dataArray[indexPath.row];
YourCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
if ([self checkWhetherImageAlreadyExist]) {
[cell.imageView setImage:model.image];
} else {
//show placeholder to avoid nothing in your UI, or your user gets confused
[cell.imageView setImage:placeholderImage];
[self startDownloadImageForIndexPath:indexPath];
}
}
- (void)startDownloadImageForIndexPath:(NSIndexPath *)indexPath
{
//YourImageDownloader is a class to fetch data from server
//imageDownloadsInProgress is a NSMutableDictionary to record the download process, which can avoid repeat download
YourImageDownloader *downloader = [self.imageDownloadsInProgress objectForKey:indexPath];
if (downloader == nil) {
YourDataModel *model = self.dataArray[indexPath.row];
//configure downloader
downloader = [[YourImageDownloader alloc] init];
[downloader setURL:model.url];
[downloader setCompletionHandler:^{
//download the image to local, or you can pass the image to the block
model.image = [UIImage imageWithContentsOfFile:model.localPath];
YourCell *cell = [self.mCollectionView cellForItemAtIndexPath:indexPath];
[cell.imageView setImage:model.image];
//remove downloader from dictionary
[self.imageDownloadsInProgress removeObjectForKey:indexPath];
}];
//add downloader to dictionary
[self.imageDownloadsInProgress setObject:downloader forKey:indexPath];
//start download
[downloader startDownload];
}
}
使用课程下载图像。如果您在一个集合视图中有许多图像,则可以考虑在发生内存警告时将这些图像保存到本地。如果现在很多,只需将图像保留在内存中并将其显示在集合视图中。
Use a class to download the image. If you have many images in one collection view, you may consider to save these images to local in case of memory warning. if now many, just leave the image in memory and display it in your collection view.
后面的代码是将图像保存到本地并在显示时从本地读取图像数据。
the code followed is save the image to local and read image data from local when displaying.
in .h:
#import <Foundation/Foundation.h>
@interface PortraitDownloader : NSObject
@property (nonatomic, copy) NSString *portraitName;
@property (nonatomic, copy) void (^completionHandler)(void);
- (void)startDownload;
- (void)cancelDownload;
@end
in .m
#import "PortraitDownloader.h"
#import <CFNetwork/CFNetwork.h>
#import "NSString+ImagePath.h" // it's a category to get the image local path
@interface PortraitDownloader ()
@property (nonatomic, strong) NSMutableData *activeDownload;
@property (nonatomic, strong) NSURLConnection *portraitConnection;
@end
@implementation PortraitDownloader
- (void)startDownload
{
self.activeDownload = [NSMutableData data];
NSString *urlstr = [NSString serverPortraitPathWithPortrait:self.portraitName];
NSURL *url = [NSURL URLWithString:urlstr];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
self.portraitConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)cancelDownload
{
[self.portraitConnection cancel];
self.portraitConnection = nil;
self.activeDownload = nil;
}
#pragma mark - NSURLConnectionDelegate
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.activeDownload appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
// Clear the activeDownload property to allow later attempts
self.activeDownload = nil;
// Release the connection now that it's finished
self.portraitConnection = nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// save to local path
NSString *localSavePath = [NSString localPortraitPathWithPortrait:self.portraitName];
[self.activeDownload writeToFile:localSavePath atomically:YES];
self.activeDownload = nil;
// Release the connection now that it's finished
self.portraitConnection = nil;
// call our delegate and tell it that our icon is ready for display
if (self.completionHandler) {
self.completionHandler();
}
}
@end
如果你想把你的图像保留在内存中,只需将完成块修改为:
if you want to leave your image in-memory, just modify the completion block as:
in .h
typedef void (^Completion_handle) (UIImage *image);
@interface PortraitDownloader : NSObject
@property (nonatomic, copy) Completion_handle myCompletionBlock;
和.m
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// get image from data
UIImage *image = [UIImage imageWithData:self.activeDownload];
self.activeDownload = nil;
// Release the connection now that it's finished
self.portraitConnection = nil;
// call our delegate and tell it that our icon is ready for display
if (self.myCompletionBlock) {
self.myCompletionBlock(image);
}
}
并修改方法startDownloadImageForIndexPath,将图像保存到你的保留它的模型
and also modify methods startDownloadImageForIndexPath, save the image to your model to retain it
这篇关于ios:将新数据加载到UICollectionView中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!