-
Notifications
You must be signed in to change notification settings - Fork 274
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* develop: (30 commits) fix didEnterTimes logic change to common runloop modes fix a bug of outerScrollView feature: cannot work correctly when LazyScrollView is not outerScrollView's direct subview. fix some issues modify the ModelBucket interface a little Add load item views "async" feature modify the loadMoreData interface add loadMore feature and demo for it use model bucket to replace origin logic add TMLazyModelBucket and unit test for it fix some issues tidy the assemble logic add test project rename properties add autoClearGestures feature add a demo for outerScrollView update demo update outScrollView feature add reuse pool class 1. tidy codes 2. remove the delegate forwarding logic and hack setContentOffset directly ... # Conflicts: # README.md
- Loading branch information
Showing
54 changed files
with
2,802 additions
and
1,320 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,22 +2,18 @@ Pod::Spec.new do |s| | |
|
||
s.name = "LazyScroll" | ||
s.version = "1.0.0" | ||
s.summary = "A ScrollView to resolve the problem of reusability of views." | ||
|
||
s.description = <<-DESC | ||
It reply an another way to control reuse in a ScrollView, it depends on give a special reuse identifier to every view controlled in LazyScrollView. | ||
DESC | ||
|
||
s.summary = "A ScrollView to resolve the problem of reusability of views." | ||
s.homepage = "https://github.com/alibaba/LazyScrollView" | ||
s.license = { :type => 'MIT' } | ||
s.author = { "fydx" => "[email protected]", | ||
"HarrisonXi" => "[email protected]" } | ||
s.platform = :ios | ||
s.ios.deployment_target = "5.0" | ||
s.ios.deployment_target = "7.0" | ||
s.source = { :git => "https://github.com/alibaba/LazyScrollView.git", :tag => "1.0.0" } | ||
s.source_files = "LazyScrollView/*.{h,m}" | ||
s.requires_arc = true | ||
s.prefix_header_contents = '#import <TMUtils/TMUtils.h>' | ||
|
||
s.dependency 'TMUtils', '~> 1.0' | ||
s.dependency 'TMUtils', '~> 1.0.0' | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// | ||
// LazyScroll.h | ||
// LazyScrollView | ||
// | ||
// Copyright (c) 2015-2018 Alibaba. All rights reserved. | ||
// | ||
|
||
#ifndef LazyScroll_h | ||
#define LazyScroll_h | ||
|
||
#import "TMLazyItemViewProtocol.h" | ||
#import "TMLazyItemModel.h" | ||
#import "TMLazyReusePool.h" | ||
#import "TMLazyModelBucket.h" | ||
#import "UIView+TMLazyScrollView.h" | ||
#import "TMLazyScrollView.h" | ||
|
||
#endif /* LazyScroll_h */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// | ||
// TMLazyItemModel.h | ||
// LazyScrollView | ||
// | ||
// Copyright (c) 2015-2018 Alibaba. All rights reserved. | ||
// | ||
|
||
#import <Foundation/Foundation.h> | ||
#import <CoreGraphics/CoreGraphics.h> | ||
|
||
/** | ||
It is a model to store data of item view. | ||
*/ | ||
@interface TMLazyItemModel : NSObject | ||
|
||
/** | ||
Item view's frame in LazyScrollView. | ||
*/ | ||
@property (nonatomic, assign) CGRect absRect; | ||
@property (nonatomic, readonly) CGFloat top; | ||
@property (nonatomic, readonly) CGFloat bottom; | ||
|
||
/** | ||
Item view's unique ID in LazyScrollView. | ||
Will be set to string value of index if it's nil. | ||
The ID MUST BE unique. | ||
*/ | ||
@property (nonatomic, copy) NSString *muiID; | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// | ||
// TMLazyItemModel.m | ||
// LazyScrollView | ||
// | ||
// Copyright (c) 2015-2018 Alibaba. All rights reserved. | ||
// | ||
|
||
#import "TMLazyItemModel.h" | ||
|
||
@implementation TMLazyItemModel | ||
|
||
- (CGFloat)top | ||
{ | ||
return CGRectGetMinY(_absRect); | ||
} | ||
|
||
- (CGFloat)bottom | ||
{ | ||
return CGRectGetMaxY(_absRect); | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// | ||
// TMLazyItemViewProtocol.h | ||
// LazyScrollView | ||
// | ||
// Copyright (c) 2015-2018 Alibaba. All rights reserved. | ||
// | ||
|
||
/** | ||
If the item view in LazyScrollView implements this protocol, it | ||
can receive specified event callback in LazyScrollView's lifecycle. | ||
*/ | ||
@protocol TMLazyItemViewProtocol <NSObject> | ||
|
||
@optional | ||
/** | ||
Will be called if the item view is dequeued in | ||
'dequeueReusableItemWithIdentifier:' method. | ||
It is similar with 'prepareForReuse' method of UITableViewCell. | ||
*/ | ||
- (void)mui_prepareForReuse; | ||
/** | ||
Will be called if the item view is loaded into buffer area. | ||
This callback always is used for setup item view. | ||
It is similar with 'viewDidLoad' method of UIViewController. | ||
*/ | ||
- (void)mui_afterGetView; | ||
/** | ||
Will be called if the item view enters the visible area. | ||
The times starts from 0. | ||
If the item view is in the visible area and the LazyScrollView | ||
is reloaded, this callback will not be called. | ||
This callback always is used for user action tracking. Sometimes, | ||
it is also used for starting timer event. | ||
*/ | ||
- (void)mui_didEnterWithTimes:(NSUInteger)times; | ||
/** | ||
Will be called if the item view leaves the visiable area. | ||
This callback always is used for stopping timer event. | ||
*/ | ||
- (void)mui_didLeave; | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// | ||
// TMLazyModelBucket.h | ||
// LazyScrollView | ||
// | ||
// Copyright (c) 2015-2018 Alibaba. All rights reserved. | ||
// | ||
|
||
#import <Foundation/Foundation.h> | ||
#import "TMLazyItemModel.h" | ||
|
||
/** | ||
Every bucket store item models in an area. | ||
1st bucket store item models which Y value is from 0 to bucketHeight. | ||
2nd bucket store item models which Y value is from bucketHeight to bucketHeight * 2. | ||
*/ | ||
@interface TMLazyModelBucket : NSObject | ||
|
||
@property (nonatomic, assign, readonly) CGFloat bucketHeight; | ||
|
||
- (instancetype)initWithBucketHeight:(CGFloat)bucketHeight; | ||
|
||
- (void)addModel:(TMLazyItemModel *)itemModel; | ||
- (void)addModels:(NSSet<TMLazyItemModel *> *)itemModels; | ||
- (void)removeModel:(TMLazyItemModel *)itemModel; | ||
- (void)removeModels:(NSSet<TMLazyItemModel *> *)itemModels; | ||
- (void)reloadModel:(TMLazyItemModel *)itemModel; | ||
- (void)reloadModels:(NSSet<TMLazyItemModel *> *)itemModels; | ||
- (void)clear; | ||
- (NSSet<TMLazyItemModel *> *)showingModelsFrom:(CGFloat)startY to:(CGFloat)endY; | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
// | ||
// TMLazyModelBucket.m | ||
// LazyScrollView | ||
// | ||
// Copyright (c) 2015-2018 Alibaba. All rights reserved. | ||
// | ||
|
||
#import "TMLazyModelBucket.h" | ||
|
||
@interface TMLazyModelBucket () { | ||
NSMutableArray<NSMutableSet *> *_buckets; | ||
} | ||
|
||
@end | ||
|
||
@implementation TMLazyModelBucket | ||
|
||
@synthesize bucketHeight = _bucketHeight; | ||
|
||
- (instancetype)initWithBucketHeight:(CGFloat)bucketHeight | ||
{ | ||
if (self = [super init]) { | ||
_bucketHeight = bucketHeight; | ||
_buckets = [NSMutableArray array]; | ||
} | ||
return self; | ||
} | ||
|
||
- (void)addModel:(TMLazyItemModel *)itemModel | ||
{ | ||
if (itemModel && itemModel.bottom > itemModel.top) { | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong. |
||
NSInteger startIndex = (NSInteger)floor(itemModel.top / _bucketHeight); | ||
NSInteger endIndex = (NSInteger)floor((itemModel.bottom - 0.01) / _bucketHeight); | ||
for (NSInteger index = 0; index <= endIndex; index++) { | ||
if (_buckets.count <= index) { | ||
[_buckets addObject:[NSMutableSet set]]; | ||
} | ||
if (index >= startIndex && index <= endIndex) { | ||
NSMutableSet *bucket = [_buckets objectAtIndex:index]; | ||
[bucket addObject:itemModel]; | ||
} | ||
} | ||
} | ||
} | ||
|
||
- (void)addModels:(NSSet<TMLazyItemModel *> *)itemModels | ||
{ | ||
if (itemModels) { | ||
for (TMLazyItemModel *itemModel in itemModels) { | ||
[self addModel:itemModel]; | ||
} | ||
} | ||
} | ||
|
||
- (void)removeModel:(TMLazyItemModel *)itemModel | ||
{ | ||
if (itemModel) { | ||
for (NSMutableSet *bucket in _buckets) { | ||
[bucket removeObject:itemModel]; | ||
} | ||
} | ||
} | ||
|
||
- (void)removeModels:(NSSet<TMLazyItemModel *> *)itemModels | ||
{ | ||
if (itemModels) { | ||
for (NSMutableSet *bucket in _buckets) { | ||
[bucket minusSet:itemModels]; | ||
} | ||
} | ||
} | ||
|
||
- (void)reloadModel:(TMLazyItemModel *)itemModel | ||
{ | ||
[self removeModel:itemModel]; | ||
[self addModel:itemModel]; | ||
} | ||
|
||
- (void)reloadModels:(NSSet<TMLazyItemModel *> *)itemModels | ||
{ | ||
[self removeModels:itemModels]; | ||
[self addModels:itemModels]; | ||
} | ||
|
||
- (void)clear | ||
{ | ||
[_buckets removeAllObjects]; | ||
} | ||
|
||
- (NSSet<TMLazyItemModel *> *)showingModelsFrom:(CGFloat)startY to:(CGFloat)endY | ||
{ | ||
NSMutableSet *result = [NSMutableSet set]; | ||
NSInteger startIndex = (NSInteger)floor(startY / _bucketHeight); | ||
NSInteger endIndex = (NSInteger)floor((endY - 0.01) / _bucketHeight); | ||
for (NSInteger index = 0; index <= endIndex; index++) { | ||
if (_buckets.count > index && index >= startIndex && index <= endIndex) { | ||
NSSet *bucket = [_buckets objectAtIndex:index]; | ||
[result unionSet:bucket]; | ||
} | ||
} | ||
NSMutableSet *needToBeRemoved = [NSMutableSet set]; | ||
for (TMLazyItemModel *itemModel in result) { | ||
if (itemModel.top >= endY || itemModel.bottom <= startY) { | ||
[needToBeRemoved addObject:itemModel]; | ||
} | ||
} | ||
[result minusSet:needToBeRemoved]; | ||
return [result copy]; | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// | ||
// TMLazyReusePool.h | ||
// LazyScrollView | ||
// | ||
// Copyright (c) 2015-2018 Alibaba. All rights reserved. | ||
// | ||
|
||
#import <UIKit/UIKit.h> | ||
|
||
@interface TMLazyReusePool : NSObject | ||
|
||
- (void)addItemView:(UIView *)itemView forReuseIdentifier:(NSString *)reuseIdentifier; | ||
- (UIView *)dequeueItemViewForReuseIdentifier:(NSString *)reuseIdentifier; | ||
- (UIView *)dequeueItemViewForReuseIdentifier:(NSString *)reuseIdentifier andMuiID:(NSString *)muiID; | ||
- (void)clear; | ||
- (NSSet<UIView *> *)allItemViews; | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// | ||
// TMLazyReusePool.m | ||
// LazyScrollView | ||
// | ||
// Copyright (c) 2015-2018 Alibaba. All rights reserved. | ||
// | ||
|
||
#import "TMLazyReusePool.h" | ||
#import "UIView+TMLazyScrollView.h" | ||
|
||
@interface TMLazyReusePool () { | ||
NSMutableDictionary<NSString *, NSMutableSet *> *_reuseDict; | ||
} | ||
|
||
@end | ||
|
||
@implementation TMLazyReusePool | ||
|
||
- (instancetype)init | ||
{ | ||
if (self = [super init]) { | ||
_reuseDict = [NSMutableDictionary dictionary]; | ||
} | ||
return self; | ||
} | ||
|
||
- (void)addItemView:(UIView *)itemView forReuseIdentifier:(NSString *)reuseIdentifier | ||
{ | ||
if (reuseIdentifier == nil || reuseIdentifier.length == 0 || itemView == nil) { | ||
return; | ||
} | ||
NSMutableSet *reuseSet = [_reuseDict tm_safeObjectForKey:reuseIdentifier]; | ||
if (!reuseSet) { | ||
reuseSet = [NSMutableSet set]; | ||
[_reuseDict setObject:reuseSet forKey:reuseIdentifier]; | ||
} | ||
[reuseSet addObject:itemView]; | ||
} | ||
|
||
- (UIView *)dequeueItemViewForReuseIdentifier:(NSString *)reuseIdentifier | ||
{ | ||
return [self dequeueItemViewForReuseIdentifier:reuseIdentifier andMuiID:nil]; | ||
} | ||
|
||
- (UIView *)dequeueItemViewForReuseIdentifier:(NSString *)reuseIdentifier andMuiID:(NSString *)muiID | ||
{ | ||
if (reuseIdentifier == nil || reuseIdentifier.length == 0) { | ||
return nil; | ||
} | ||
UIView *result = nil; | ||
NSMutableSet *reuseSet = [_reuseDict tm_safeObjectForKey:reuseIdentifier]; | ||
if (reuseSet && reuseSet.count > 0) { | ||
if (!muiID) { | ||
result = [reuseSet anyObject]; | ||
} else { | ||
for (UIView *itemView in reuseSet) { | ||
if ([itemView.muiID isEqualToString:muiID]) { | ||
result = itemView; | ||
break; | ||
} | ||
} | ||
if (!result) { | ||
result = [reuseSet anyObject]; | ||
} | ||
} | ||
[reuseSet removeObject:result]; | ||
} | ||
return result; | ||
} | ||
|
||
- (void)clear | ||
{ | ||
[_reuseDict removeAllObjects]; | ||
} | ||
|
||
- (NSSet<UIView *> *)allItemViews | ||
{ | ||
NSMutableSet *result = [NSMutableSet set]; | ||
for (NSMutableSet *reuseSet in _reuseDict.allValues) { | ||
[result unionSet:reuseSet]; | ||
} | ||
return [result copy]; | ||
} | ||
|
||
@end |
Oops, something went wrong.
@HarrisonXi 类似这种condition
itemModel.bottom > itemModel.top
,是不是放在TMLazyItemModel内部比较合适呢