一、准备数据
面试:属性和成员变量的区别?
>属性:提供了 getter & setter 和 成员变量
>成员变量
注意:真正保存数据的是“成员变量”。
//面试:类扩展、匿名分类,定义私有属性或方法
ViewController (){成员变量可以定义在这个位置 }
但走向工作岗位会发现有些人会把成员变量定义在
@implementation ViewController {
Xcode7的泛型?有了泛型可以指定容器类中对象的类型了。
例:NSArray <NSString *> * strings = @“sun”, @“yuan”];
例:NSDictionary <NSString *, NSNumber *> *map = @{@“a”:@1 }
}
@implementation ViewController {
NSArray <NSURL *> *_urls;
}
//加载数据
- (void)loadData{
NSMutableArray *arrayM = [NSMutableArray array];
for (int i = 0; i<3; i++) {
NSString *fileName = [NSString stringWithFormat: @“%02zd.jpg”, (i + 1) ];
//提示:如果fileName 不存在 url返回 nil
NSURL *url =[ [NSBundle mainBundle] URLForResource: fileName withExtension: nil ];
[arrayM addObjecr: url];
}
_urls = arrayM.copy;
}
二、搭建界面
1.封装一个轮播器的 视图。 <—— urls(collectionView)
>.定义一个CZLoopView类
- (instancetype)initWithURLs: (NSArray <NSURL *> *) urls{
//一定要是UICollectionViewFlowLayout
self = [super initWithFrame: CGRectZero collectionViewLayout:[ [UICollectionViewFlowLayout alloc]init ];
if (self) {
_urls = urls;
self.dataSource = self;
//注册class
[self registerClass: [UICollectionViewCell class] forCellWithReuseIdentifier:CZLoopViewCellID ];
}
return self;
}
2.传递数据。
在初始化方法中加一个urls参数
3.设置数据源。
>遵守协议
@interface CZLoopView ( ) <UICollectionViewDataSource>
>实现协议方法
1)numberOfItemsInSection…{
return _urls.count;
}
2) 定义一个cell的重用标识符 NSStirng *const CZLoopViewCellID = @“CZLoopViewCellID”;——>注册class
cellForItemAtIndexPath:…{
//创建cell
UICollectionViewCell *cell = [collectionView dequeue…];
//注册cell
}
4.自定义cell布局。
>定义一个类继承自UICollectionViewFlowLayout——>即创建一个布局的子类。
- (void)prepareLayout { }——>”重写控件的布局“——>在collectionView的第一次布局的时候,被调用,此时,collectionView的frame已经设置完毕了。
注意:这个方法很好用,不用考虑视图view的生命周期。
5.自定义cell,显示图像。
>collectionViewCell 的 frame 是根据之前的 layout 已经确定好的
//添加图像视图
_imageView =[ [UIImageView alloc] initithFrame: self.bounds];
[self. contentView addSubview: _imageView];
>给cell定义一个url属性
>重写属性的set方法
>根据URL 获取二进制数据
NSData *data = [NSData dataWithContentsOfURL..]
UIImage *image = [UIImage imageWithData: data];
_imageView.image = image;
>cell.url = _urls[indexPath.item];
6.实现轮播,可以左右拖拽——>利用dispatch_async在主队列异步,保证数据源方法执行完毕后,再滚动collectionView.
>一组实现。
scrollToItemAtIndexPath:
面试题:在开发中,什么时候使用过多线程,不用说AFN!
dispatch_async(dispatch_get_main_queue )——>主队列:1)安排任务在主线程上执行。2)如果主线程当前有任务,主队列暂时不调度任务。
提示:公司的项目中可能会出现viewDidLoad中有大量的主队列异步的!
7.无限轮播—监听滚动的位置
滚动停止后: 第0页,跳转到,第1组的第0页
最后一页,跳转到第0组的最后一页。
//代理方法---滚动视图停止滚动。
scrollViewDidEndDecelerating...
面试题: 避免图片少,解决快速滚动图片轮播器的卡顿,因为跑到offset的else分支内,做offset的设置,可以适当的将数据源放大,可以解决卡顿。—>因为collectionView能够很好的复用。