UICollectionViewCell以编程方式内存泄漏

时间:2013-09-20 09:34:11

标签: ios uicollectionview

我在不使用故事板的情况下以编程方式创建了UICollectionViewUICollectionViewCell,但发生了一些事情,我无法理解原因。

BKPhotoCell中存在内存泄漏。

单元格是全屏的,但滚动CollectionView时,它们永远不会重复使用。每个Init都会调用indexpath.row

PrepareForReuse也从未打过电话。

任何人都可以帮助我理解我做错了什么吗?

- (void)viewDidLoad
{
    [super viewDidLoad];

        CGSize screenSize = self.view.bounds.size;
        UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
        [flowLayout setItemSize:CGSizeMake(screenSize.width, screenSize.height)];
        [flowLayout setMinimumInteritemSpacing:0.0f];
        [flowLayout setMinimumLineSpacing:0.0f];
        [flowLayout setSectionInset:UIEdgeInsetsMake(0, 0, 0, 0)];

        [flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];

        self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0,0, screenSize.width, screenSize.height)  collectionViewLayout:flowLayout];
        [self.collectionView setDelegate:self];
        [self.collectionView setDataSource:self];
        [self.collectionView registerClass:[BKPhotoCell class] forCellWithReuseIdentifier:@"BKPhotoCell"];
        [self.collectionView setPagingEnabled:YES];
        [self.collectionView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
        [self.view addSubview:self.collectionView];

}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    BKPhotoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"BKPhotoCell" forIndexPath:indexPath];
    [cell.imageView setImage:[UIImage imageNamed:[_photos objectAtIndex:indexPath.row]]];
    return cell;
}

BKPhotoCell.h:

@interface BKPhotoCell : UICollectionViewCell
    @property (nonatomic, strong) UIImageView *imageView;
@end

BKPhotoCell.m:

@interface BKPhotoCell() <UIScrollViewDelegate>
@property (nonatomic ,strong) UIScrollView *scrollView;
@end

@implementation BKPhotoCell

#define isPortrait [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortrait || [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown

#pragma mark - ScrollView Delegate

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {

    return self.imageView;
}

- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{

    CGFloat offsetX = (scrollView.bounds.size.width > scrollView.contentSize.width)?
    (scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5 : 0.0;

    CGFloat offsetY = (scrollView.bounds.size.height > scrollView.contentSize.height)?
    (scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5 : 0.0;

    _imageView.center = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX,
                                 scrollView.contentSize.height * 0.5 + offsetY);
}

#pragma mark - View Lifecycle

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {

        self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.contentView.bounds.size.width, self.contentView.bounds.size.height)];
        [self.scrollView setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth];
        [self.scrollView setContentMode:UIViewContentModeScaleAspectFit];
        [self.scrollView setDelegate:self];
        [self.contentView addSubview:_scrollView];

        self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.contentView.bounds.size.width, self.contentView.bounds.size.height)];
        [self.imageView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
        [self.imageView setContentMode:UIViewContentModeScaleAspectFit];

        [self.scrollView addSubview:self.imageView];

    }
    return self;
}


- (void)prepareForReuse {

    [super prepareForReuse];
    NSLog(@"Prepare for reuse");

}

- (void)layoutSubviews {

    [super layoutSubviews];

    [self.imageView  setFrame:CGRectMake(0, 0, _imageView.image.size.width, _imageView.image.size.height)];
    // NSLog(@"Setting Content Size: %f, %f", _imageView.image.size.width, _imageView.image.size.height);
    [_scrollView setContentSize:_imageView.image.size];

    CGFloat offsetX = (_scrollView.bounds.size.width > _scrollView.contentSize.width)?
    (_scrollView.bounds.size.width - _scrollView.contentSize.width) * 0.5 : 0.0;

    CGFloat offsetY = (_scrollView.bounds.size.height > _scrollView.contentSize.height)?
    (_scrollView.bounds.size.height - _scrollView.contentSize.height) * 0.5 : 0.0;

    _imageView.center = CGPointMake(_scrollView.contentSize.width * 0.5 + offsetX,
                                    _scrollView.contentSize.height * 0.5 + offsetY);

    float minimumZoomScale;

    if (isPortrait) {
        minimumZoomScale = _imageView.frame.size.width >= _imageView.frame.size.height ? _scrollView.frame.size.width / _imageView.frame.size.width : _scrollView.frame.size.height / _imageView.frame.size.height;
    } else {
        minimumZoomScale = _imageView.frame.size.width > _imageView.frame.size.height ? _scrollView.frame.size.width / _imageView.frame.size.width : _scrollView.frame.size.height / _imageView.frame.size.height;
    }

    [self.scrollView setMinimumZoomScale:minimumZoomScale];
    [self.scrollView setMaximumZoomScale:minimumZoomScale * 2];
    [self.scrollView setZoomScale:minimumZoomScale];


}

1 个答案:

答案 0 :(得分:2)

如果您使用的是iOS7,则可能是您遇到了重用错误!

我确实有同样的问题,它在iOS6.1iOS6上工作正常,但只要它在iOS7(最终)上启动,单元格就永远不会被重用!

我没有修复,我正在尝试创建自己的重用逻辑。

编辑:

我有一些工作,所以你需要从布局中保存属性(如果你使用它可能会覆盖FlowLayout)。

然后在

- (void)collectionView:(UICollectionView *)collectionView 
  didEndDisplayingCell:(UICollectionViewCell *)cell 
    forItemAtIndexPath:(NSIndexPath *)indexPath

将您的单元格保存为NSMutableArray

in

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

检查数组中的单元格并应用属性,例如:

UICollectionViewCell *cell;

if (![_removedCells count]) {
    cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier 
                                                     forIndexPath:indexPath];
} else {
    cell = [_removedCells lastObject];
    [_removedCells removeLastObject];
    [cell prepareForReuse];        
    UICollectionViewLayoutAttributes* attr = [_layout getTempAttribute:indexPath];

    [cell setFrame: attr.frame];        
    [cell applyLayoutAttributes:attr];

    if (![cell superview]) {
        [_collectionView addSubview:cell];
    }
}

getTempAttribute 只是从position检索我UICollectionViewCell的先前计算的UICollectionViewLayout,所以只需按indexPath查找并返回{ {1}},它看起来好像工作正常UICollectionViewLayoutAttributes reusing - 但我无法保证任何事情; - )

Edit2:经过进一步测试后,我必须得出结论:打破 UICollectionViewCells中的旋转,导致奇怪的布局问题!