UIScrollView实现重用

#import <UIKit/UIKit.h>

 

@interface Test19ViewCell : UIView


// 索引

@property (nonatomic, assign) NSUInteger index;

// 文本

@property (nonatomic, copy) NSString *text;

// 文本控件

@property (nonatomic, retain) UILabel *textLabel;

// 图片名称

@property (nonatomic, retain) NSString *imageName;

// 图片控件 

@property (nonatomic, retain) UIImageView *imageView;

@end


 

#import "Test19ViewCell.h"

@implementation Test19ViewCell

@synthesize index = _index;

@synthesize textLabel = _textLabel;

@synthesize text = _text;

@synthesize imageName = _imageName;

@synthesize imageView = _imageView;


- (void)dealloc{

    [_textLabel release];

    [_text release];

    [_imageView release];

    [_imageName release];

    [super dealloc];

}


- (id)init{

    if (self = [super init]) {

        self.backgroundColor = [UIColor yellowColor];

    }

    return self;

}


- (UILabel *)textLabel{

    if (_textLabel == nil) {

        _textLabel = [[UILabel allocinitWithFrame:self.bounds];

        _textLabel.textAlignment = UITextAlignmentCenter;

        _textLabel.backgroundColor = self.backgroundColor;

        _textLabel.contentMode = UIViewContentModeCenter;

        [self addSubview:_textLabel];

    }

    return _textLabel;

}


- (void)setText:(NSString *)text{

    if (text != nil) {

        [_text release];

        _text = [text copy];

        self.textLabel.text = _text;

    }

}


- (UIImageView *)imageView{

    if (_imageView == nil) {

        CGFloat padding = 2.f;

        CGFloat x = padding;

        CGFloat y = padding;

        CGFloat width = 40;

        CGFloat height = 40;

        _imageView = [[UIImageView allocinit];

        _imageView.frame = CGRectMake(x, y, width, height);

        [self addSubview:_imageView];

    }

    return _imageView;

}


- (void)setImageName:(NSString *)imageName{

    if (imageName != nil) {

        [_imageName release];

        _imageName = [imageName copy];

        self.imageView.image = [UIImage imageNamed:_imageName];

    }

}

 

@end


 

#import <Foundation/Foundation.h>


@interface Test19ViewController : UIViewController<UIScrollViewDelegate>


// 数据源

@property (nonatomic, retain) NSMutableArray *dataSource;

// 可见的cell集合

@property (nonatomic, retain) NSMutableSet *visibleCells;

// 可循环的cell集合

@property (nonatomic, retain) NSMutableSet *recycledCells;

// UIScrollView

@property (nonatomic, retain) UIScrollView *scrollView;

@end


 


#import "Test19ViewController.h"

#import "Test19ViewCell.h"

#define kCellSize CGSizeMake(self.view.frame.size.width, 44)

#define kCellSeparatePadding    1.0

@interface Test19ViewController()


// 根据下标设置对应的frame、index、text

- (void)configureCell:(Test19ViewCell *)cell forIndex:(NSUInteger)index;

// 判断index对应的视图是否在可见队列中

- (BOOL)isVisibleCellForIndex:(NSUInteger)index;

// 重用

- (id)dequeueReusableCell;

// 显示文本

- (void)showCells;

@end


@implementation Test19ViewController

@synthesize dataSource = _dataSource;

@synthesize visibleCells = _visibleCells;

@synthesize recycledCells = _recycledCells;

@synthesize scrollView = _scrollView;


- (void)dealloc{

    [_dataSource release];

    [_visibleCells release];

    [_recycledCells release];

    [_scrollView release];

    [super dealloc];

}


- (void)loadView{

    _scrollView = [[UIScrollView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    _scrollView.backgroundColor = [UIColor whiteColor];

    _scrollView.delegate = self;

    self.view = _scrollView;

}


- (void)viewDidLoad{

    [super viewDidLoad];

    _recycledCells = [[NSMutableSet allocinit];

    _visibleCells = [[NSMutableSet allocinit];

    _dataSource = [[NSMutableArray allocinit];

    

    [_dataSource addObject:@"Zero"];

    [_dataSource addObject:@"One"];

    [_dataSource addObject:@"Two"];

    [_dataSource addObject:@"Three"];

    [_dataSource addObject:@"Four"];

    [_dataSource addObject:@"Five"];

    [_dataSource addObject:@"Six"];

    [_dataSource addObject:@"Seven"];

    [_dataSource addObject:@"Eight"];

    [_dataSource addObject:@"Nine"];

    [_dataSource addObject:@"Ten"];

    [_dataSource addObject:@"Eleven"];

    [_dataSource addObject:@"Tewlve"];

    [_dataSource addObject:@"Thirdteen"];

    [_dataSource addObject:@"Fourteen"];

    [_dataSource addObject:@"Fifteen"];

    [_dataSource addObject:@"Sixteen"];

    [_dataSource addObject:@"Seventeen"];

    [_dataSource addObject:@"Eightteen"];

    

    _scrollView.contentSize = CGSizeMake(_scrollView.frame.size.width, (kCellSize.height +kCellSeparatePadding) * [_dataSource count] - kCellSeparatePadding);

    [self showCells];

}


#pragma mark - Private Custom Methods

// 根据下标设置对应的frame、index、text

- (void)configureCell:(Test19ViewCell *)cell forIndex:(NSUInteger)index{

    // 设置index

    cell.index = index;

    CGFloat x = 0;

    CGFloat y = (kCellSeparatePadding + kCellSize.height) * index;

    CGFloat width = kCellSize.width;

    CGFloat height = kCellSize.height;

    // 设置frame

    cell.frame = CGRectMake(x, y, width, height);

    // 设置显示文本text

    cell.text = [_dataSource objectAtIndex:index];

    // 设置显示图片名称

    cell.imageName = [NSString stringWithFormat:@"%d.jpeg",index % 8];

}


// 判断index对应的视图是否在可见队列中

- (BOOL)isVisibleCellForIndex:(NSUInteger)index{

    BOOL isVisible = NO;

    for (Test19ViewCell *cell in _visibleCells) {

        if (cell.index == index) {

            isVisible = YES;

            break;

        }

    }

    return isVisible;

}


// 重用

- (id)dequeueReusableCell{

    Test19ViewCell *cell = [_recycledCells anyObject];      // retain count = 1;

    if (cell != nil) {

        [[cell retainautorelease];                                    // retain count = 2 ,but it seems retain count = 1

        [_recycledCells removeObject:cell];                       // retain count = 1 now and autorelease

    }

    return cell;

}

// 用于测试实际创建cell的数量

static int testCount = 0;

- (void)showCells{

    // 当前UIScrollView的可见区域

    CGRect visibleBounds = _scrollView.bounds;

    // 此处存在一定的误差

    int firstNeededCellIndex = floorf(CGRectGetMinY(visibleBounds) / (kCellSize.height +kCellSeparatePadding));

    int lastNeededICellIndex = floorf(CGRectGetMaxY(visibleBounds) / (kCellSize.height +kCellSeparatePadding));

    firstNeededCellIndex = MAX(firstNeededCellIndex, 0);

    lastNeededICellIndex  = MIN(lastNeededICellIndex, [_dataSource count] - 1);

    

    NSLog(@"%d------%d",firstNeededCellIndex,lastNeededICellIndex);

    // 循环可见视图,将不在当前可见范围视图添加到循环队列中,然后从父视图中移除

    for (Test19ViewCell *cell in _visibleCells) {

        if (cell.index < firstNeededCellIndex || cell.index > lastNeededICellIndex) {

            [_recycledCells addObject:cell];        // retain count + 1

            [cell removeFromSuperview];          // retain count - 1

        }

    }

    

    // 可见视图的集合减去循环队列的集合

    [_visibleCells minusSet:_recycledCells];

    // 添加缺少的cell

    for (int index = firstNeededCellIndex; index <= lastNeededICellIndex; index ++) {

        if (![self isVisibleCellForIndex:index]) {

            // 先取循环队列中寻找对应的数据

            Test19ViewCell *cell = [self dequeueReusableCell];

            // 如果没有找到可用的,则创建一个新的

            if (cell == nil) {

                cell = [[[Test19ViewCell allocinitautorelease];

                testCount ++;

            }

            // 设置下标、frame、text

            [self configureCell:cell forIndex:index];

            // 将其添加到视图中

            [_scrollView addSubview:cell];

            // 加入到可见队列中

            [_visibleCells addObject:cell];

        }

    }

}


#pragma mark - UIScrollViewDelegate Methods

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

    [self showCells];

    NSLog(@"count ------> %d",testCount);

}

@end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值