UICollectionView 重新加载(崩溃)

Posted

技术标签:

【中文标题】UICollectionView 重新加载(崩溃)【英文标题】:UICollectionView reload ( crash ) 【发布时间】:2013-09-06 12:19:29 【问题描述】:

我有一个集合视图,当我最初加载数据时该视图工作正常,但当我尝试重新加载它时崩溃。看看方法上发生的重新加载 - scrollViewDidEndDecelerating

错误是

-[FeedCollectionViewCell release]: message sent to deallocated instance 0x800d6f70

这里是代码。 这是Controller

@interface MyViewController : UIViewController <UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout, UIScrollViewDelegate>




@property (retain, nonatomic) IBOutlet UICollectionView *collectionView;

@end

这是实现:

@implementation MyViewController

@interface FeedCollectionViewController ()
@property (nonatomic, strong) NSMutableArray *dataArray;
-(void)getData;
@end

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) 
        // Custom initialization
        if (self.dataArray == nil) 
            self.dataArray = [[NSMutableArray alloc] init];
        
    
    return self;


- (void)viewDidLoad


[self.collectionView registerClass:[FeedCollectionViewCell class] forCellWithReuseIdentifier:[FeedCollectionViewCell reuseIdentifier]];


    // Configure layout
    UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
    [flowLayout setItemSize:CGSizeMake(153, 128)];
    [flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
    [self.collectionView setCollectionViewLayout:flowLayout];

    [self getData];




-(void)getData

 // here I make a call to the server to get the data and I set the data array
   self.dataArray = mydatafromserver
   [self.collectionView reloadData];


- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath;


    FeedCollectionViewCell *cell = (FeedCollectionViewCell *)[cv dequeueReusableCellWithReuseIdentifier:[FeedCollectionViewCell reuseIdentifier] forIndexPath:indexPath];

    [cell.label setText:[[self.dataArray objectAtIndex:indexPath.row] name];

    return cell;


- (void)scrollViewDidEndDecelerating:(UICollectionView *) collectionView

    NSLog(@"FeedCollectionViewController::scrollViewDidEndDecelerating");
    CGPoint offset = collectionView.contentOffset;
    CGRect bounds = collectionView.bounds;
    CGSize size = collectionView.contentSize;
    UIEdgeInsets inset = collectionView.contentInset;
    float y = offset.y + bounds.size.height - inset.bottom;
    float h = size.height;

      //   NSLog(@"offset: %f", offset.y);
      //   NSLog(@"content.height: %f", size.height);
      //   NSLog(@"bounds.height: %f", bounds.size.height);
      //   NSLog(@"inset.top: %f", inset.top);
      //   NSLog(@"inset.bottom: %f", inset.bottom);
      //   NSLog(@"pos: %f of %f", y, h);

    float reload_distance = 300;
    if(y > h - reload_distance) 
        NSLog(@"load more rows...");

***//// FAIL HERE***       
        [self.collectionView reloadData];

    

这是单元格

#import <UIKit/UIKit.h>
#define FB_COLL_CELL_IDENTIFIER     @"CollectionCellIdentifier"

@interface FeedCollectionViewCell : UICollectionViewCell


@property (retain, nonatomic) IBOutlet UIImageView *image;
@property (retain, nonatomic) IBOutlet UILabel *label;

@property (retain, nonatomic) IBOutlet UIActivityIndicatorView *spinner;
+ (NSString *)reuseIdentifier;

@end

#import "FeedCollectionViewCell.h"
#import "CustomCellBackground.h"

@implementation FeedCollectionViewCell


- (id)initWithFrame:(CGRect)frame

    self = [super initWithFrame:frame];
    if (self) 
        NSLog(@"FeedCollectionViewCell initWithFrame");
        // Initialization code
        NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"FeedCollectionViewCell" owner:self options:nil];

        if ([arrayOfViews count] < 1) 
            return nil;
        

        if (![[arrayOfViews objectAtIndex:0] isKindOfClass:[UICollectionViewCell class]]) 
            return nil;
        

        self = [arrayOfViews objectAtIndex:0];

        CustomCellBackground *backgroundView = [[CustomCellBackground alloc] initWithFrame:CGRectZero];
        self.selectedBackgroundView = backgroundView;

    

    return self;




+ (NSString *)reuseIdentifier

    NSLog(@"FBDisplayCell ... static reuseIdentifier called ");
    return (NSString *)FB_COLL_CELL_IDENTIFIER;



@end

这是另一个。添加这个是因为它正在被使用。我不认为问题在这里,但你永远不知道!

#import <UIKit/UIKit.h>

@interface CustomCellBackground : UIView

@end

#import "CustomCellBackground.h"

@implementation CustomCellBackground

- (id)initWithFrame:(CGRect)frame

    self = [super initWithFrame:frame];
    if (self) 
        // Initialization code
    
    return self;


- (void)drawRect:(CGRect)rect

    // draw a rounded rect bezier path filled with blue
    CGContextRef aRef = UIGraphicsGetCurrentContext();
    CGContextSaveGState(aRef);
    UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:5.0f];
    [bezierPath setLineWidth:5.0f];
    [[UIColor blackColor] setStroke];

    UIColor *fillColor = [UIColor colorWithRed:0.529 green:0.808 blue:0.922 alpha:1]; // color equivalent is #87ceeb
    [fillColor setFill];

    [bezierPath stroke];
    [bezierPath fill];
    CGContextRestoreGState(aRef);


@end

【问题讨论】:

您在没有 ARC 的项目中使用 UICollectionView。框架允许吗? 有没有什么好办法找出来? 不知道,一直在使用ARC。它已经存在了很多年。你在某个地方调用[FeedCollectionViewCell release],而它已经发布了,这就是问题所在。 我检查了我的编译器,我正在使用这个编译器:Apple LLVM compiler 4.2 以及,关于发布。这就是我的困惑所在,我没有发布 feedCollectionViewCell。我没有用于发布的代码。 【参考方案1】:

问题在于 UICollectioViewCell -initWithFrame

我改为不加载笔尖,我开始创建自己的笔尖

- (id)initWithFrame:(CGRect)frame

    self = [super initWithFrame:frame];
    if (self) 
        self.backgroundColor = [UIColor colorWithWhite:0.85f alpha:1.0f];

        self.layer.borderColor = [UIColor whiteColor].CGColor;
        self.layer.borderWidth = 3.0f;
        self.layer.shadowColor = [UIColor blackColor].CGColor;
        self.layer.shadowRadius = 3.0f;
        self.layer.shadowOffset = CGSizeMake(0.0f, 2.0f);
        self.layer.shadowOpacity = 0.5f;

        self.imageView = [[UIImageView alloc] initWithFrame:self.bounds];
        self.imageView.contentMode = UIViewContentModeScaleAspectFill;
        self.imageView.clipsToBounds = YES;

        [self.contentView addSubview:self.imageView];
    
    return self;
    

【讨论】:

以上是关于UICollectionView 重新加载(崩溃)的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionViewFlowLayout 子类在滚动和重新加载时崩溃访问超出范围的数组

加载 UICollectionView 时崩溃,为啥?

如果在重新加载期间触摸单元格,则重新加载后无法选择 UICollectionView 单元格

多个 UiCollectionview 重新加载问题

UICollectionView:重新加载数据,不删除单元内动画

UICollectionView 仅重新加载第一个单元格