3

我在不使用情节提要的情况下以编程方式创建了一个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];


}
4

1 回答 1

2

如果您正在使用iOS7 它,您可能会遇到重用错误!

我确实有同样的问题,它在iOS6.1and上运行良好iOS6,但是一旦它开始iOS7(最终),单元格就永远不会被重用!

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

编辑:

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

然后在

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

将您的单元格保存到NSMutableArray.

- (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为 my计算UICollectionViewCell的值UICollectionViewLayout,因此只需查找indexPath并返回UICollectionViewLayoutAttributes,它看起来好像工作正常并且reusing-UICollectionViewCells但我不能保证任何事情 ;-)

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

于 2013-09-20T10:40:46.773 回答