最近由于公司项目需求,需要在app首页轮播数条公告,一直没有找到合适的第三方,最后决定自己撸一个。公告显示使用UICollectionView,无限循环滚动参考了SDCycleScrollView,UICollectionView数据源方法中单元格的个数为待轮播的公告数组个数*100,自动滚动定时器才用GCD方法创建。该项目目前仅实现了基本功能,后期可以根据相应需求进行调整。
// 创建定时器队列
dispatch_queue_t queue = dispatch_queue_create("Cycle Message", NULL);
/*
第一个参数:dispatch_source_type_t type为设置GCD源方法的类型,前面已经列举过了。
第二个参数:uintptr_t handle Apple的API介绍说,暂时没有使用,传0即可。
第三个参数:unsigned long mask Apple的API介绍说,使用DISPATCH_TIMER_STRICT,会引起电量消耗加剧,毕竟要求精确时间,所以一般传0即可,视业务情况而定。
第四个参数:dispatch_queue_t _Nullable queue 队列,将定时器事件处理的Block提交到哪个队列之上。可以传Null,默认为全局队列
*/
_gcdTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
// 定时器相关参数设置,第二个参数:开始时间 第三个参数:时间间隔 第四个参数:允许误差时间,传0即可
dispatch_source_set_timer(_gcdTimer, DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC, 0.0 * NSEC_PER_SEC);
/*
第一个参数:dispatch_source_t source,...不用说了。
第二个参数:dispatch_block_t _Nullable handler,定时器执行的动作,需要处理的业务逻辑Block。
*/
dispatch_source_set_event_handler(_gcdTimer, ^{
dispatch_async(dispatch_get_main_queue(), ^{
[selfautomaticScroll];
});
});
//启动定时器
dispatch_resume(_gcdTimer);
无限滚动参考SDCycleScrollView,
/**
公告自动轮播,2s执行一次
*/
- (void)automaticScroll{
if(0==_messages.count){
return;
}
intcurrentIndex = [selfcurrentIndex];
inttargetIndex = currentIndex +1;
[selfscrollToIndex:targetIndex];
}
/**
滚动到指定索引
@param targetIndex 待滚动到的索引位置
*/
- (void)scrollToIndex:(int)targetIndex{
if(targetIndex >=_messages.count*100) {
targetIndex =_messages.count*100*0.5;
[self.contentView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
return;
}
[self.contentView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:targetIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:YES];
}
/**
获取当前显示的公告索引
@return 索引
*/
- (int)currentIndex{
intindex =0;
index = (self.contentView.contentOffset.y + CGRectGetHeight(self.frame) * 0.5) / CGRectGetHeight(self.frame);
returnMAX(0, index);
}
注意:因为自动滚动的方法中应到的NSIndexPath方法用的是indexPathForItem:targetIndex创建,所以在UICollectionView的数据源方法中取值时用的方法为NSInteger index = indexPath.item%_messages.count;才用%取模运算,保证不会因为数组越界导致crash!!!!!!
具体实现代码可以参考:PhoneContactManager