iOS开发学习之无限滚动UICollectionView和BUG解决措施

(一) 无限滚动之UICollectionView

您好、

平时我们经常在图片浏览器中会翻看一些图片,对于这会滚动的效果实现,我们第一个直觉会想到的UIscrollview。首先我们会考虑到View的一些循环利用,一般情况下会创建两到三个View去实现它的来回的切换滚动。


不过今天虾米没用到这种方法。虾米用的是UICollectionView。

那下面 小虾米通过小作业来实现无限滚动,如果当中有什么不好的或者是需要改善的地方,请告诉我您的建议和意见。同时也可以联系虾米。

我们私下可以交流交流。。。。xieixe!!


自动滚动大致意图:




虾米先把大体需要用到的类都放在每一个对应位置上,方便以后查找某一个类和元素。

先浏览一下整体的classes。然后虾米再附上每一个类的代码实现 。 如下图:



我们先在故事板里,拉入一个UICollectionView(最好和图片的尺寸一样 )和一个UIPageController。如下图:

注意:根控制器的class要改为JHNewsController. 并且collectionView的代理和数据源方法为self(根控制器)

可以在collectionView上右击拉线给News Controller或者用代码实现。。。^-^ 嘻嘻。。。







然后,在根控制器当中我们必须遵守UICollectionView的一些协议。

虾米先把根控制器的主要实现代码po上。


大致为:

通过添加一个定时器实现三组数据的无限循环滚动。

主要方法是   [self.collectionView scrollToItemAtIndexPath: atScrollPosition: animated:YES]; 同时也要计算出需要展示的位置。

自动滚动下一页请详细看看我下面所写的方法 -(void)nextPage。


代码如下:

//  JHNewsController.m
//  无限滚动-02新闻数据显示
//
//  Created by cjj on 15-9-19.
//  Copyright (c) 2015年 jh.chen. All rights reserved.
//

#import "JHNewsController.h"
#import "JHNewsCell.h"
#import "JHNews.h"
#import "MJExtension.h"

#define JHReuseIdentifierCell @"news"
#define JHMaxSection 3

@interface JHNewsController () <UICollectionViewDataSource,UICollectionViewDelegate>
@property (nonatomic, strong) NSArray *newses;
@property (nonatomic, strong) NSTimer *timer;
@property (weak, nonatomic) IBOutlet UIPageControl *pageControl;
@property (weak, nonatomic) IBOutlet UICollectionView *collectionView;

@end

@implementation JHNewsController
- (NSArray *)newses
{
    if (_newses == nil) {
        self.newses = [JHNews objectArrayWithFilename:@"newses.plist"];
        self.pageControl.numberOfPages = self.newses.count;
    }
    return _newses;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 注册cell
    [self.collectionView registerNib:[UINib nibWithNibName:@"JHNewsCell" bundle:nil] forCellWithReuseIdentifier:JHReuseIdentifierCell];
    
    // "默认"显示最中间那组
    [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:JHMaxSection / 2] atScrollPosition:UICollectionViewScrollPositionLeft animated:YES];
    
    // 添加定时器
    [self addTimer];
}

/*
 *  添加定时器
 */
-(void)addTimer
{
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(nextPage) userInfo:nil repeats:YES];
    
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    self.timer = timer;
}


-(void)nextPage
{
    // 1.显示当前的位置信息
    NSIndexPath *currentIndexPath = [[self.collectionView indexPathsForVisibleItems] lastObject];
    
    // 马上显示中间那组的数据
    NSIndexPath *currentIndexPathReset = [NSIndexPath indexPathForItem:currentIndexPath.item inSection:JHMaxSection / 2];
    [self.collectionView scrollToItemAtIndexPath:currentIndexPathReset atScrollPosition:UICollectionViewScrollPositionLeft animated:NO];
    
    // 2.计算出下一个需要展示的位置
    NSUInteger nextItem = currentIndexPathReset.item + 1;
    NSUInteger nextSection = currentIndexPathReset.section;
    if (nextItem == self.newses.count) {
        nextItem = 0;
        nextSection ++;
    }
    NSIndexPath *nextIndexPath = [NSIndexPath indexPathForItem:nextItem inSection:nextSection];
    
    // 3.通过动画滚动到下一个位置
    [self.collectionView scrollToItemAtIndexPath:nextIndexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:YES];
}

/*
 *  移除定时器
 */
-(void)removeTimer
{
    [self.timer invalidate];
    self.timer = nil;
}




#pragma mark - UICollectionViewDataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return self.newses.count;
}

-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return JHMaxSection;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    JHNewsCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:JHReuseIdentifierCell forIndexPath:indexPath];
    
    cell.news = self.newses[indexPath.item];
    
    return cell;
}

#pragma mark - UICollectionViewDelegate

/**
 *  当用户开始拖拽时就会调用
 */
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self removeTimer];
}

/**
 *  当用户停止拖拽时就会调用
 */
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    [self addTimer];
}

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    // 显示下一页
    int page = (int)(scrollView.contentOffset.x / scrollView.bounds.size.width + 0.5) % self.newses.count;
    self.pageControl.currentPage =page;
}

@end


另外。。。我们有必要了解下JHNewsCell,虾米通过继承UICollectionViewCell,并创建附有一个Xib属性。里面封装着一个UIImageView和一个UILabel

.h文件留下一个接口,让别人传递数据进来,我们拿到外边传进来的数据在.m文件通过set方法实现。。。


详细代码如下:

//
//  JHNewsCell.m
//  无限滚动-02新闻数据显示
//
//  Created by cjj on 15-9-19.
//  Copyright (c) 2015年 jh.chen. All rights reserved.
//

#import "JHNewsCell.h"
#import "JHNews.h"

@interface JHNewsCell()

@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
@property (weak, nonatomic) IBOutlet UIImageView *iconView;

@end


@implementation JHNewsCell


- (void)setNews:(JHNews *)news
{
    _news = news;
    self.iconView.image = [UIImage imageNamed:news.icon];
    self.titleLabel.text = [NSString stringWithFormat:@"  %@",news.title];
}

@end


(二) BUG解决措施

在写这份demo的时候,遇到一些让我纠结了半天而程序莫名崩溃的bug,为此虾米把它记录了下来。

上面写的代码,检查了很多遍都没有问题。但运行时出现了错误,报如下的错误:


*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'invalid nib registered for identifier (news) - nib must contain exactly one top level object which must be a UICollectionReusableView instance’



最终还是被我找到了错误原因:在自定义xib的时候,额外多了一个控件在cell另外的区域,把该控件删除即可。

如图:


把多余的UIImageView删除即可,说到底还是自己太马虎从而犯了简单的错误了。


如果有什么好的建议,请联系虾米,虾米感激不尽 蟹蟹 哈!!微笑微笑

虾米联系方式:

QQ:584837022

github:https://github.com/ios-cjh



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值