ios:将新数据加载到UICollectionView中 [英] ios: load new data into UICollectionView

查看:105
本文介绍了ios:将新数据加载到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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆