这是一篇发现问题和解决问题的笔记。
遇到的问题
每次上拉加载更多完成执行[self.tableView reloadData]
后,banner都会增加两页。
banner是一个cell,它的setModel
方法代码是这样的:
- (void)setModel:(CWFSpecialSaleBannerModel *)model {
_model = model;
self.pageControl.numberOfPages = _model.banners.count;
if (_model.banners.count == 0) {
[self.collectionView reloadData];
return;
}
CWFSpecialSaleBannerItemModel *firstModel = model.banners.lastObject;
CWFSpecialSaleBannerItemModel *lastModel = model.banners.firstObject;
[_model.banners addObject:lastModel];
[_model.banners insertObject:firstModel atIndex:0];
[self.collectionView reloadData];
if (self.collectionView.contentOffset.x == 0) {
self.collectionView.contentOffset = CGPointMake(self.bounds.size.width, 0);
}
[self resetTimer];
}
这里首尾添加两个元素是为了做轮播效果。
问题所在
setModel的时候
_model = model;
这句代码乍看之下好像没什么问题,但是:
CWFSpecialSaleBannerItemModel *firstModel = model.banners.lastObject;
CWFSpecialSaleBannerItemModel *lastModel = model.banners.firstObject;
[_model.banners addObject:lastModel];
[_model.banners insertObject:firstModel atIndex:0];
我的本意是给_model的banners数组添加两个元素,但这同时,也无意中给model的banners数组添加了两个元素,这就导致每次上拉加载更多[tableView reloadData]
时调用banner cell的setModel
都会给数据源里的model.banners数组增加两个元素。
解决问题
我想要的效果是对_model执行操作并不影响model。
想要一个相同的对象,但是对它进行操作又不影响原对象,自然而然想到了深拷贝,但是并不是所有类的对象都像NSArray
对象具有深拷贝资格,只有遵从了NSMutableCopying
协议的类的对象才能深拷贝。
所以要对model进行改写:
@interface CWFSpecialSaleBannerModel ()<NSMutableCopying>
@end
@implementation CWFSpecialSaleBannerModel
- (id)mutableCopyWithZone:(NSZone *)zone {
CWFSpecialSaleBannerModel *model = [[[self class] allocWithZone:zone] init];
// 这里也要mutableCopy哦
model.banners = self.banners.mutableCopy;
return model;
}
@end
setModel的时候,使用深拷贝的model:
- (void)setModel:(CWFSpecialSaleBannerModel *)model {
_model = model.mutableCopy;
// ....
}
这样就不会因为改动_model而导致数据源的改动了。
总结
以前关于深浅拷贝的博客没有白看。
你看完我的这篇笔记后相信有了更深刻的认识。
不说了,吃鸡
网友评论