LazyScrollView是阿里iOS端,針對ScrollView做的一個解決異構(與TableView的同構對比)滾動視圖的複用回收問題的解決方案。
LazyScrollView文檔
蘋果核 - iOS 高性能異構滾動視圖構建方案 —— LazyScrollView
使用場景
一般的如果是同一類型的cell,或者cell類型不是特別多的話TableView實現起來還是比較方便。
LazyScrollView是爲了解決view種類特別多,使用TableView定製cell麻煩的問題。
這個開源庫比較早了,我看最後更新是在兩年前,使用LazyScrollView還是使用tableView需要根據具體的業務來定。
Demo
集成
pod ‘LazyScroll’
如果報缺少framework的庫的話,將Podfile裏面的 use_frameworks!
行註釋掉,添加上 use_modular_headers!
使用靜態庫好了。因爲我的確是遇到這個問題,所以這裏贅述一下。
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'Test-1' do
# Comment the next line if you don't want to use dynamic frameworks
# use_frameworks!
use_modular_headers!
# Pods for Test-1
pod 'LazyScroll'
end
Demo
開元庫裏面的Demo演示簡單明瞭,很容易讀,自己寫了一個與Demo中思想有點不同的是,我創建旅了一個類ScrollViewItemModel,這個類作爲數據源模型。
- ScrollViewItemModel
ScrollViewItemModel.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "TMLazyItemModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface ScrollViewItemModel : NSObject
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithTMLazyItem:(TMLazyItemModel *)item;
// TMLazyItemModel
@property (nonatomic, strong, readonly) TMLazyItemModel *item;
// 內容
@property (nonatomic, copy) NSString *text;
// 背景顏色
@property (nonatomic, strong) UIColor *backgroundColor;
@end
NS_ASSUME_NONNULL_END
ScrollViewItemModel.m
#import "ScrollViewItemModel.h"
@interface ScrollViewItemModel ()
@property (nonatomic, strong, readwrite) TMLazyItemModel *item;
@end
@implementation ScrollViewItemModel
- (instancetype)initWithTMLazyItem:(TMLazyItemModel *)item {
if (self = [super init]) {
self.item = item;
}
return self;
}
@end
- ViewController
ViewController.m
#import "ViewController.h"
#import "LazyScroll.h"
#import "ScrollViewItemModel.h"
@interface ViewController ()<TMLazyScrollViewDataSource>
@property (nonatomic, strong) TMLazyScrollView *scrollView;
@property (nonatomic, strong) NSMutableArray <ScrollViewItemModel *> *dataSource;
@end
@implementation ViewController
- (TMLazyScrollView *)scrollView {
if (!_scrollView) {
_scrollView = [[TMLazyScrollView alloc] initWithFrame:self.view.bounds];
_scrollView.autoAddSubview = YES;
_scrollView.dataSource = self;
}
return _scrollView;;
}
- (NSMutableArray<ScrollViewItemModel *> *)dataSource {
if (!_dataSource) {
_dataSource = [[NSMutableArray alloc] init];
}
return _dataSource;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self initViews];
[self initData];
}
- (void)initViews {
[self.view insertSubview:self.scrollView atIndex:0];
}
- (void)initData {
CGFloat maxY = 0;
CGFloat currentY = 20;
CGFloat viewWidth = CGRectGetWidth(self.view.bounds);
for (int i = 0; i < 15; i++)
{
TMLazyItemModel *item = [[TMLazyItemModel alloc] init];
item.absRect = CGRectMake(10 + (i % 2) * ((viewWidth - 20 + 3) / 2), i / 2 * 80 + currentY, (viewWidth - 20 - 3) / 2, 80 - 3);
ScrollViewItemModel *model = [[ScrollViewItemModel alloc] initWithTMLazyItem:item];
model.text = [NSString stringWithFormat:@"%d",i];
model.backgroundColor = [ViewController randomColor];
[self.dataSource addObject:model];
if (CGRectGetMaxY(item.absRect) > maxY) {
maxY = CGRectGetMaxY(item.absRect);
}
}
currentY = maxY + 10;
for (int i = 0; i < 15; i++)
{
TMLazyItemModel *item = [[TMLazyItemModel alloc] init];
item.absRect = CGRectMake(10, i * 80 + currentY, viewWidth - 20, 80 - 3);
ScrollViewItemModel *model = [[ScrollViewItemModel alloc] initWithTMLazyItem:item];
model.text = [NSString stringWithFormat:@"%d",i+15];
model.backgroundColor = [ViewController randomColor];
[self.dataSource addObject:model];
if (CGRectGetMaxY(item.absRect) > maxY) {
maxY = CGRectGetMaxY(item.absRect);
}
}
currentY = maxY + 10;
for (int i = 0; i < 15; i++)
{
TMLazyItemModel *item = [[TMLazyItemModel alloc] init];
item.absRect = CGRectMake((i % 2) * (viewWidth - 20 + 3) / 2 + 10, i / 2 * 80 + currentY, (viewWidth - 20 - 3) / 2, 80 - 3);
ScrollViewItemModel *model = [[ScrollViewItemModel alloc] initWithTMLazyItem:item];
model.text = [NSString stringWithFormat:@"%d",i+30];
model.backgroundColor = [ViewController randomColor];
[self.dataSource addObject:model];
if (CGRectGetMaxY(item.absRect) > maxY) {
maxY = CGRectGetMaxY(item.absRect);
}
}
self.scrollView.contentSize = CGSizeMake(CGRectGetWidth(self.view.bounds), maxY+10);
[self.scrollView reloadData];
}
#pragma mark - TMLazyScrollViewDataSource
- (NSUInteger)numberOfItemsInScrollView:(nonnull TMLazyScrollView *)scrollView {
return self.dataSource.count;
}
- (nonnull TMLazyItemModel *)scrollView:(nonnull TMLazyScrollView *)scrollView
itemModelAtIndex:(NSUInteger)index {
return self.dataSource[index].item;
}
- (nonnull UIView *)scrollView:(nonnull TMLazyScrollView *)scrollView
itemByMuiID:(nonnull NSString *)muiID
{
static NSString *reusableIdentifier = @"ViewController_TMLazyScrollView";
UILabel *label = (UILabel *)[scrollView dequeueReusableItemWithIdentifier:reusableIdentifier];
if (label == nil) {
label = [[UILabel alloc] init];
label.textAlignment = NSTextAlignmentCenter;
label.numberOfLines = 0;
label.reuseIdentifier = reusableIdentifier;
NSLog(@"創建了新的label");
}
//讀view對應的index
NSInteger index = [muiID integerValue];
//從數據源中取出對應的數據模型
ScrollViewItemModel *model = self.dataSource[index];
//給view賦值等其他操作在這裏處理
label.text = model.text;
label.backgroundColor = model.backgroundColor;
//這裏一定要注意設置view的frame
label.frame = model.item.absRect;
return label;
}
#pragma mark Private
+ (UIColor *)randomColor {
CGFloat hue = (arc4random() %256/256.0);
CGFloat saturation = (arc4random() %128/256.0) +0.5;
CGFloat brightness = (arc4random() %128/256.0) +0.5;
return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1.0];
}
@end
整體上和阿里提供的Demo差不多,使用方法什麼的人家的文檔裏面說的非常清楚,唯一一點不同是我將ScrollViewItemModel作爲一個純粹的數據模型,它裏面包含有我們view上所需要的任何數據,包括TMLazyItemModel的實例,這樣一是做一個簡單的功能擴展,二是也不用每次刷新都去創建TMLazyItemModel的實例。
上面這些只是簡單的會用,讀源碼的話會使我們學習更多。