将更多图像添加到已运行的UICollectionView中

时间:2014-08-30 23:39:03

标签: ios objective-c iphone uiscrollview

我有一个我在viewDidLoad中设置的UICollectionView,并在此之后立即添加图像。当用户滚动到某一点时,我尝试添加更多图像但是集合视图不会加载新图像

如何重新加载或添加更多图像到我的滚动视图

#pragma mark - New Retrieve
- (void) rwDataToPlist {

    // Step1: Get plist file path

    NSArray *sysPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory ,NSUserDomainMask, YES);

    NSString *documentsDirectory = [sysPaths objectAtIndex:0];

    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"news.plist"];

    NSLog(@"Plist File Path: %@", filePath);

    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {

         stuff = [[NSArray alloc] initWithContentsOfFile:filePath];
        //NSLog(@"Stuff %@", stuff);
        [self sortRetrievedData];
     } else {


     }


}

-(void)sortRetrievedData {
    titles = [stuff valueForKey:kKeyTitle];
    thumbMediaUrl = [stuff valueForKey:kKeyThumbUrl];
    thumbWidth = [stuff valueForKey:kKeyThumbWidth];
    thumbHeight = [stuff valueForKey:kKeyThumbHeight];

    for(NSArray *array in titles) {
        for (NSArray *realArray in array) {
            titles = realArray;
        }
    }
    for(NSArray *array in thumbMediaUrl) {
        for(NSDictionary *dict in array) {
            thumbMediaUrl = dict;
        }
    }
    for(NSArray *array in thumbWidth) {
        for(NSDictionary *dict in array) {
            thumbWidth = dict;
        }
    }
    for(NSArray *array in thumbHeight) {
        for(NSDictionary *dict in array) {
            thumbHeight = dict;
        }
    }
}

#pragma mark - Collection View
#pragma mark - Display Collection 
-(void)displayCollection {
    UIColor *myColor = [UIColor colorWithRed:(245.0 / 255.0) green:(245.0 / 255.0) blue:(245.0 / 255.0) alpha: 1];

    CGRect screenBound = [[UIScreen mainScreen] bounds];
    CGSize screenSize = screenBound.size;
    CGFloat screenWidth = screenSize.width;
    CGFloat screenHeight = screenSize.height;
    self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    CGRect locOfScree = CGRectMake(0, 64, screenWidth, screenHeight - 44);

    UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
    imageDisplayer = [[UICollectionView alloc] initWithFrame:locOfScree collectionViewLayout:layout];
    [imageDisplayer setDataSource:self];
    [imageDisplayer setDelegate:self];

    UINib *nib = [UINib nibWithNibName:@"CollectionViewCell" bundle:nil];
    [imageDisplayer registerNib:nib forCellWithReuseIdentifier:CellIdentifier];
    [imageDisplayer setBackgroundColor:myColor];

    [self.view insertSubview:imageDisplayer belowSubview:navBar];
    //[self.view addSubview:imageDisplayer];
}

#pragma mark - Setup

- (void)setupData
{
    self.imageURLStrings = [NSMutableArray array];

    // Save image to docs directory so we can get a nice URL
    // Not sure how to get the URL from an asset catalog off the top of my head

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"greyBurger.png"];

    UIImage *image = [UIImage imageNamed:@"greyBurger"];
    NSData *data = UIImagePNGRepresentation(image);
    [data writeToFile:path atomically:YES];

    // Populate our imageURLStrings array with many paths

    for (NSInteger i = 0; i < NumberOfImages; i++)
    {
        [self.imageURLStrings addObject:path];
        //NSLog(@"Path %@", path);
    }
}

- (void)setupCollectionView
{
    UINib *nib = [UINib nibWithNibName:@"CollectionViewCell" bundle:nil];
    [self.collectionView registerNib:nib forCellWithReuseIdentifier:CellIdentifier];
}

#pragma mark - UICollectionView Datasource

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    //return [self.imageURLStrings count];
    return [titles count];
    //return 2;

}



- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CollectionViewCell *cell = (CollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];


    //NSLog(@"CELL FOR COUNT:%lu", [titles count]);
    NSString *title = [titles objectAtIndex:indexPath.row];
    cell.backgroundColor = [UIColor whiteColor];
    NSString *imageUrl = [thumbMediaUrl objectForKey:title];
    NSURL *thumbUrl = [NSURL URLWithString:imageUrl];
    UIImageView *imageView = [[UIImageView alloc] init];
    NSData *imageData = [NSData dataWithContentsOfURL:thumbUrl];
    imageView.image = [UIImage imageWithData:imageData];

    cell.backgroundView = imageView;
    cell.layer.shouldRasterize = YES;
    cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
    //cell.frame = CGRectMake(0, 0, 100, 100);

    //cell.imageURLString = [self.imageURLStrings objectAtIndex:indexPath.item];

    return cell;
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CGRect screenBound = [[UIScreen mainScreen] bounds];
    CGSize screenSize = screenBound.size;
    CGFloat screenWidth = screenSize.width;

    NSString *title = [titles objectAtIndex:indexPath.row];
    float width = [[thumbWidth objectForKey:title] floatValue];
    float height = [[thumbHeight objectForKey:title] floatValue];
    float imageWidth = (screenWidth / 2) - 3;
    float scale = imageWidth / width;
    float imageHeight = height * scale;
    CGSize imageSize = CGSizeMake(imageWidth, imageHeight);


    return imageSize;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
    return 2.0;
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
    return 2.0;
}

// Layout: Set Edges
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    // return UIEdgeInsetsMake(0,8,0,8);  // top, left, bottom, right
    return UIEdgeInsetsMake(0,0,0,0);  // top, left, bottom, right
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSArray* attributesToReturn = [self layoutAttributesForElementsInRect:rect];
    for (UICollectionViewLayoutAttributes* attributes in attributesToReturn)
    {
        if (nil == attributes.representedElementKind)
        {
            NSIndexPath* indexPath = attributes.indexPath;
            attributes.frame = [self layoutAttributesForItemAtIndexPath:indexPath].frame;
        }
    }
    return attributesToReturn;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
     UICollectionViewLayoutAttributes* currentItemAttributes = [self layoutAttributesForItemAtIndexPath:indexPath];

    if (indexPath.item < numColumns){
        CGRect f = currentItemAttributes.frame;
        f.origin.y = 0;
        currentItemAttributes.frame = f;
        return currentItemAttributes;
    }
    NSIndexPath* ipPrev = [NSIndexPath indexPathForItem:indexPath.item-numColumns inSection:indexPath.section];
    CGRect fPrev = [self layoutAttributesForItemAtIndexPath:ipPrev].frame;
    CGFloat YPointNew = fPrev.origin.y + fPrev.size.height + 10;
    CGRect f = currentItemAttributes.frame;
    f.origin.y = YPointNew;
    currentItemAttributes.frame = f;
    return currentItemAttributes;
}

我根据前两个答案的建议更改了我的代码,现在我必须将图像添加到正在运行的视图中。并使每列具有各自独立的高度,因此每个边缘有2px的间距,这是我尝试重新加载数据

-(void)refreshView {


    [self rwDataToPlist];
    [self.collectionView reloadData];
    [self setupCollectionView];
}

3 个答案:

答案 0 :(得分:2)

启动iOS6本身Apple推出了UICollectionView。您可以使用UICollectionView和Pull to Bottom Refresh来实现目标。它看起来像UITableView Pull to Bottom Refresh。

以下是UIcollectionView的一些参考:

Source Code

  1. Beginning UICollectionView
  2. UICollectionView with StoryBoard
  3. 创建UICollectionView后,您需要为UICollectionView添加PulltoBottom Refresh,如下面的代码:

    -(void)viewWillAppear:(BOOL)animated
    {
    
    [self.collectionView.infiniteScrollingView setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhite];
    [self.collectionView addInfiniteScrollingWithActionHandler:^{
        ////(@"Infinitescroll");
    
    
    
    
    
    
    
        @try {
            int64_t delayInSeconds = 2.0;
            dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
            dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
                //[self.dataSource addObjectsFromArray:tmp];
                [self.collectionView performBatchUpdates:^{
    
    
                } completion:nil];
                [self.collectionView.infiniteScrollingView stopAnimating];
            });
        }
        @catch (NSException *exception) {
    
        }
    
    
    
    
    
    }];
    
    [super viewWillAppear:animated];
    }
    

    对于下面的代码,您必须添加一些文件:

    SVPulltoReferesh Link

答案 1 :(得分:1)

一些建议/问题:

  1. 不知道您的特定问题的限制,听起来您正在尝试显示图像网格的某些外观,并在用户滚动超过某个点时加载图像的“下一页”。看起来像UITableView或UICollectionView是一个更合适的机制来做你正在尝试做的事情。这两个类都将处理延迟加载的图像,通过正确配置的数据源进行分页,自动进行contentSize调整,并且在没有mainThread冻结的情况下将会非常快速。它们也基于MVC设计模式,可能会澄清上面代码中的一些设计。

  2. 加载更多图像时UI /滚动冻结的原因可能是由于从磁盘读取userDefaults和图像数据本身。磁盘操作可能很昂贵,尤其是一次很多。如果必须以这种方式加载元数据和图像文件,请考虑通过GCD的dispatch_async在后​​台线程上执行此处理。

  3. 第二组图像未出现的原因可能是由于图像帧或scrollView contentSize误算。通过向scrollView而不是UIImageViews添加一系列彩色UIView来考虑调试,并考虑将contentSize.height硬编码为比您需要的大得多的东西。你还有NSLogged图像帧和contentSize以确保它们匹配吗?

  4. 修改

    这是一个使用UICollectionView和后台线程的快速示例项目的链接,用于从磁盘读取UIImage数据(由于使用UICollectionView,这不再是必需的):

    https://github.com/alfiehanssen/SOImageGrid

    如果您有任何疑问,请告诉我,希望我的目标并不完全不合适。

答案 2 :(得分:-2)

我使用前两个答案中建议的UICollectionView并添加了CHTCollectionViewWaterfallLayout以允许我想要的图像间距

我的代码:

#pragma mark - Collection View
#pragma mark - Display Collection 
-(void)displayCollection {
    UIColor *myColor = [UIColor colorWithRed:(245.0 / 255.0) green:(245.0 / 255.0) blue:(245.0 / 255.0) alpha: 1];

    CGRect screenBound = [[UIScreen mainScreen] bounds];
    CGSize screenSize = screenBound.size;
    CGFloat screenWidth = screenSize.width;
    CGFloat screenHeight = screenSize.height;
    self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    CGRect locOfScree = CGRectMake(0, 44, screenWidth, screenHeight - 44);

    CHTCollectionViewWaterfallLayout *layout = [[CHTCollectionViewWaterfallLayout alloc] init];

    layout.sectionInset = UIEdgeInsetsMake(2, 2, 2, 2);
    layout.headerHeight = 0;
    layout.footerHeight = 0;
    layout.minimumColumnSpacing = 2;
    layout.minimumInteritemSpacing = 2;
    //UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
    imageDisplayer = [[UICollectionView alloc] initWithFrame:locOfScree collectionViewLayout:layout];
    imageDisplayer.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;

    [imageDisplayer setDataSource:self];
    [imageDisplayer setDelegate:self];

    UINib *nib = [UINib nibWithNibName:@"CollectionViewCell" bundle:nil];
    [imageDisplayer registerNib:nib forCellWithReuseIdentifier:CellIdentifier];
    [imageDisplayer setBackgroundColor:myColor];

    [self.view insertSubview:imageDisplayer belowSubview:navBar];
    //[self.view addSubview:imageDisplayer];

    imageDisplayer = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
    imageDisplayer.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    imageDisplayer.dataSource = self;
    imageDisplayer.delegate = self;
    imageDisplayer.backgroundColor = [UIColor whiteColor];
    [imageDisplayer registerClass:[CHTCollectionViewWaterfallCell class]
        forCellWithReuseIdentifier:CellIdentifier];
}

#pragma mark - Setup
- (void)setupCollectionView
{
    UINib *nib = [UINib nibWithNibName:@"CollectionViewCell" bundle:nil];
    [self.collectionView registerNib:nib forCellWithReuseIdentifier:CellIdentifier];
}

#pragma mark - UICollectionView Datasource

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    //return [self.imageURLStrings count];
    return [titles count];
    //return 2;

}



- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    /*
    CollectionViewCell *cell = (CollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
    */
    CHTCollectionViewWaterfallCell *cell =
    (CHTCollectionViewWaterfallCell *)[collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier
                                                                                forIndexPath:indexPath];

    NSString *title = [titles objectAtIndex:indexPath.row];
    cell.backgroundColor = [UIColor whiteColor];
    NSString *imageUrl = [thumbMediaUrl objectForKey:title];
    NSURL *thumbUrl = [NSURL URLWithString:imageUrl];
    UIImageView *imageView = [[UIImageView alloc] init];
    NSData *imageData = [NSData dataWithContentsOfURL:thumbUrl];
    imageView.image = [UIImage imageWithData:imageData];

    cell.backgroundView = imageView;
    cell.layer.shouldRasterize = YES;
    cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
    return cell;

}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CGRect screenBound = [[UIScreen mainScreen] bounds];
    CGSize screenSize = screenBound.size;
    CGFloat screenWidth = screenSize.width;

    NSString *title = [titles objectAtIndex:indexPath.row];
    float width = [[thumbWidth objectForKey:title] floatValue];
    float height = [[thumbHeight objectForKey:title] floatValue];
    float imageWidth = (screenWidth / 2) - 3;
    float scale = imageWidth / width;
    float imageHeight = height * scale;
    CGSize imageSize = CGSizeMake(imageWidth, imageHeight);


    return imageSize;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
    return 2.0;
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
    return 2.0;
}

// Layout: Set Edges
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    // return UIEdgeInsetsMake(0,8,0,8);  // top, left, bottom, right
    return UIEdgeInsetsMake(0,0,0,0);  // top, left, bottom, right
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSArray* attributesToReturn = [self layoutAttributesForElementsInRect:rect];
    for (UICollectionViewLayoutAttributes* attributes in attributesToReturn)
    {
        if (nil == attributes.representedElementKind)
        {
            NSIndexPath* indexPath = attributes.indexPath;
            attributes.frame = [self layoutAttributesForItemAtIndexPath:indexPath].frame;
        }
    }
    return attributesToReturn;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
     UICollectionViewLayoutAttributes* currentItemAttributes = [self layoutAttributesForItemAtIndexPath:indexPath];

    if (indexPath.item < numColumns){
        CGRect f = currentItemAttributes.frame;
        f.origin.y = 0;
        currentItemAttributes.frame = f;
        return currentItemAttributes;
    }
    NSIndexPath* ipPrev = [NSIndexPath indexPathForItem:indexPath.item-numColumns inSection:indexPath.section];
    CGRect fPrev = [self layoutAttributesForItemAtIndexPath:ipPrev].frame;
    CGFloat YPointNew = fPrev.origin.y + fPrev.size.height + 10;
    CGRect f = currentItemAttributes.frame;
    f.origin.y = YPointNew;
    currentItemAttributes.frame = f;
    return currentItemAttributes;
}