diff --git a/Example/LPDCollectionViewKit.xcodeproj/xcshareddata/xcschemes/LPDCollectionViewKit-Example.xcscheme b/Example/LPDCollectionViewKit.xcodeproj/xcshareddata/xcschemes/LPDCollectionViewKit-Example.xcscheme index 8b0bbd7..e081ff3 100644 --- a/Example/LPDCollectionViewKit.xcodeproj/xcshareddata/xcschemes/LPDCollectionViewKit-Example.xcscheme +++ b/Example/LPDCollectionViewKit.xcodeproj/xcshareddata/xcschemes/LPDCollectionViewKit-Example.xcscheme @@ -26,6 +26,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" shouldUseLaunchSchemeArgsEnv = "YES"> + isEnabled = "NO"> diff --git a/Example/LPDCollectionViewKit/LPDViewController.m b/Example/LPDCollectionViewKit/LPDViewController.m index 47e4fd1..12d84f3 100644 --- a/Example/LPDCollectionViewKit/LPDViewController.m +++ b/Example/LPDCollectionViewKit/LPDViewController.m @@ -30,8 +30,10 @@ - (void)viewDidLoad { UICollectionViewFlowLayout *collectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init]; collectionViewFlowLayout.scrollDirection = UICollectionViewScrollDirectionVertical; - collectionViewFlowLayout.itemSize = CGSizeMake((UIScreen.width - 30) / 2, (UIScreen.width - 30) / 2); - collectionViewFlowLayout.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10); + collectionViewFlowLayout.itemSize = CGSizeMake((UIScreen.width - 60) / 3 , (UIScreen.width - 60) / 3); + collectionViewFlowLayout.sectionInset = UIEdgeInsetsMake(1, 1, 1, 1); + collectionViewFlowLayout.minimumLineSpacing = 10; + collectionViewFlowLayout.minimumInteritemSpacing = 10; collectionViewFlowLayout.headerReferenceSize = CGSizeMake(self.view.bounds.size.width, 30); collectionViewFlowLayout.footerReferenceSize = CGSizeMake(self.view.bounds.size.width, 1); @@ -68,6 +70,9 @@ - (void)viewDidLoad { UIBarButtonItem *insertSectionBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"is" style:UIBarButtonItemStylePlain target:self action:@selector(insertSection)]; + + UIBarButtonItem *scrollToItemAtIndexPathBarButtonItem = + [[UIBarButtonItem alloc] initWithTitle:@"scroll" style:UIBarButtonItemStylePlain target:self action:@selector(scrollToItem)]; self.navigationController.toolbarHidden = NO; [self setToolbarItems:@[addCellBarButtonItem, @@ -77,7 +82,8 @@ - (void)viewDidLoad { removeCellBarButtonItem, removeCellsBarButtonItem, replaceCellsBarButtonItem, - insertSectionBarButtonItem,] + insertSectionBarButtonItem, + scrollToItemAtIndexPathBarButtonItem] animated:YES]; @weakify(self); @@ -209,4 +215,12 @@ - (void)insertSection { [self.collectionViewModel addSectionViewModel:sectionViewModel]; } +- (void)scrollToItem { + NSArray *sections = self.collectionViewModel.collectionViewModelSections; + NSArray *items = [[sections objectAtIndex:sections.count-1] items]; +// NSIndexPath *indexPath = [NSIndexPath indexPathForRow:items.count-1 inSection:sections.count-1]; + NSIndexPath *indexPath = [NSIndexPath indexPathForRow:7 inSection:0]; + [self.collectionViewModel scrollToCollectionItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionTop animated:YES]; +} + @end diff --git a/LPDCollectionViewKit/Classes/LPDCollectionView.m b/LPDCollectionViewKit/Classes/LPDCollectionView.m index 59c6633..db759fb 100644 --- a/LPDCollectionViewKit/Classes/LPDCollectionView.m +++ b/LPDCollectionViewKit/Classes/LPDCollectionView.m @@ -20,104 +20,111 @@ @interface LPDCollectionView () @implementation LPDCollectionView - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout { - self = [super initWithFrame:frame collectionViewLayout:layout]; - if (self) { - self.backgroundColor = [UIColor colorWithRed:0.9214 green:0.9206 blue:0.9458 alpha:1.0]; - } - return self; + self = [super initWithFrame:frame collectionViewLayout:layout]; + if (self) { + self.backgroundColor = [UIColor colorWithRed:0.9214 green:0.9206 blue:0.9458 alpha:1.0]; + } + return self; } - (void)bindingTo:(__kindof id)viewModel { - NSParameterAssert(viewModel); - - self.viewModel = viewModel; - LPDCollectionViewModel *collectionViewModel = self.viewModel; - super.delegate = collectionViewModel.delegate; - super.dataSource = collectionViewModel.dataSource; - - - @weakify(self); - [[[collectionViewModel.reloadDataSignal takeUntil:[self rac_signalForSelector:@selector(removeFromSuperview)]] - deliverOnMainThread] subscribeNext:^(id x) { + NSParameterAssert(viewModel); + + self.viewModel = viewModel; + LPDCollectionViewModel *collectionViewModel = self.viewModel; + super.delegate = collectionViewModel.delegate; + super.dataSource = collectionViewModel.dataSource; + + + @weakify(self); + [[[collectionViewModel.reloadDataSignal takeUntil:[self rac_signalForSelector:@selector(removeFromSuperview)]] + deliverOnMainThread] subscribeNext:^(id x) { @strongify(self); [self reloadData]; - }]; - - [[[collectionViewModel.insertSectionsSignal takeUntil:[self rac_signalForSelector:@selector(removeFromSuperview)]] - deliverOnMainThread] subscribeNext:^(NSIndexSet *indexSet) { + }]; + + [[[collectionViewModel.scrollToItemAtIndexPathSignal takeUntil:[self rac_signalForSelector:@selector(removeFromSuperview)]] + deliverOnMainThread] subscribeNext:^(RACTuple *tuple) { + @strongify(self); + [self scrollToItemAtIndexPath:tuple.first atScrollPosition:[tuple.second integerValue] animated:[tuple.third boolValue]]; + }]; + + [[[collectionViewModel.insertSectionsSignal takeUntil:[self rac_signalForSelector:@selector(removeFromSuperview)]] + deliverOnMainThread] subscribeNext:^(NSIndexSet *indexSet) { @strongify(self); [self insertSections:indexSet]; - }]; - + }]; + [[[collectionViewModel.deleteSectionsSignal takeUntil:[self rac_signalForSelector:@selector(removeFromSuperview)]] deliverOnMainThread] subscribeNext:^(NSIndexSet *indexSet) { @strongify(self); [self deleteSections:indexSet]; - }]; - + }]; + [[[collectionViewModel.replaceSectionsSignal takeUntil:[self rac_signalForSelector:@selector(removeFromSuperview)]] deliverOnMainThread] subscribeNext:^(NSIndexSet *indexSet) { @strongify(self); - [self performBatchUpdates:^{ - [self deleteSections:indexSet]; - [self insertSections:indexSet]; - } completion:nil]; - }]; - + [self performBatchUpdates:^{ + [self deleteSections:indexSet]; + [self insertSections:indexSet]; + } completion:nil]; + }]; + [[[collectionViewModel.reloadSectionsSignal takeUntil:[self rac_signalForSelector:@selector(removeFromSuperview)]] deliverOnMainThread] subscribeNext:^(NSIndexSet *indexSet) { @strongify(self); [self reloadSections:indexSet]; - }]; - + }]; + [[[collectionViewModel.insertItemsAtIndexPathsSignal takeUntil:[self rac_signalForSelector:@selector(removeFromSuperview)]] deliverOnMainThread] subscribeNext:^(RACTuple *tuple) { - @strongify(self); - if (tuple.second) { - [self performBatchUpdates:^{ - [self insertSections:tuple.second]; - [self insertItemsAtIndexPaths:tuple.first]; - } completion:nil]; - } else { - [self insertItemsAtIndexPaths:tuple.first]; - } + @strongify(self); + if (tuple.second) { + [self performBatchUpdates:^{ + [self insertSections:tuple.second]; + [self insertItemsAtIndexPaths:tuple.first]; + } completion:nil]; + } else { + [self insertItemsAtIndexPaths:tuple.first]; + } }]; - + [[[collectionViewModel.deleteItemsAtIndexPathsSignal - takeUntil:[self rac_signalForSelector:@selector(removeFromSuperview)]] + takeUntil:[self rac_signalForSelector:@selector(removeFromSuperview)]] deliverOnMainThread] subscribeNext:^(NSArray *indexPaths) { @strongify(self); [self deleteItemsAtIndexPaths:indexPaths]; - }]; - - [[[collectionViewModel.reloadItemsAtIndexPathsSignal - takeUntil:[self rac_signalForSelector:@selector(removeFromSuperview)]] - deliverOnMainThread] subscribeNext:^(NSArray *indexPaths) { - @strongify(self); - [self reloadItemsAtIndexPaths:indexPaths]; - }]; - - [[[collectionViewModel.replaceItemsAtIndexPathsSignal - takeUntil:[self rac_signalForSelector:@selector(removeFromSuperview)]] deliverOnMainThread] subscribeNext:^(RACTuple *tuple) { - @strongify(self); - [self performBatchUpdates:^{ - if (tuple.third) { - [self insertSections:tuple.third]; - [self insertItemsAtIndexPaths:tuple.second]; - } else { - [self deleteItemsAtIndexPaths:tuple.first]; - [self insertItemsAtIndexPaths:tuple.second]; - } - } completion:nil]; - }]; + }]; + + [[[collectionViewModel.reloadItemsAtIndexPathsSignal + takeUntil:[self rac_signalForSelector:@selector(removeFromSuperview)]] + deliverOnMainThread] subscribeNext:^(NSArray *indexPaths) { + @strongify(self); + [self reloadItemsAtIndexPaths:indexPaths]; + }]; + + [[[collectionViewModel.replaceItemsAtIndexPathsSignal + takeUntil:[self rac_signalForSelector:@selector(removeFromSuperview)]] deliverOnMainThread] subscribeNext:^(RACTuple *tuple) { + @strongify(self); + [self performBatchUpdates:^{ + if (tuple.third) { + [self insertSections:tuple.third]; + [self insertItemsAtIndexPaths:tuple.second]; + } else { + [self deleteItemsAtIndexPaths:tuple.first]; + [self insertItemsAtIndexPaths:tuple.second]; + } + } completion:nil]; + }]; } - (void)setDelegate:(id)delegate { - [self.viewModel setScrollViewDelegate:delegate]; + [self.viewModel setScrollViewDelegate:delegate]; } - (void)setDataSource:(id)dataSource { - // do nothing + // do nothing } @end + diff --git a/LPDCollectionViewKit/Classes/LPDCollectionViewModel+Private.h b/LPDCollectionViewKit/Classes/LPDCollectionViewModel+Private.h index 45c04a3..b3b5bf2 100644 --- a/LPDCollectionViewKit/Classes/LPDCollectionViewModel+Private.h +++ b/LPDCollectionViewKit/Classes/LPDCollectionViewModel+Private.h @@ -18,11 +18,12 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - data signal -@property (nullable, nonatomic, strong, readonly) RACSignal *reloadDataSignal; // 请勿订阅此信号 -@property (nullable, nonatomic, strong, readonly) RACSignal *insertSectionsSignal; // 请勿订阅此信号 -@property (nullable, nonatomic, strong, readonly) RACSignal *deleteSectionsSignal; // 请勿订阅此信号 -@property (nullable, nonatomic, strong, readonly) RACSignal *replaceSectionsSignal; // 请勿订阅此信号 -@property (nullable, nonatomic, strong, readonly) RACSignal *reloadSectionsSignal; // 请勿订阅此信号 +@property (nullable, nonatomic, strong, readonly) RACSignal *reloadDataSignal; // 请勿订阅此信号 +@property (nullable, nonatomic, strong, readonly) RACSignal *scrollToItemAtIndexPathSignal; // 请勿订阅此信号 +@property (nullable, nonatomic, strong, readonly) RACSignal *insertSectionsSignal; // 请勿订阅此信号 +@property (nullable, nonatomic, strong, readonly) RACSignal *deleteSectionsSignal; // 请勿订阅此信号 +@property (nullable, nonatomic, strong, readonly) RACSignal *replaceSectionsSignal; // 请勿订阅此信号 +@property (nullable, nonatomic, strong, readonly) RACSignal *reloadSectionsSignal; // 请勿订阅此信号 @property (nullable, nonatomic, strong, readonly) RACSignal *insertItemsAtIndexPathsSignal; // 请勿订阅此信号 @property (nullable, nonatomic, strong, readonly) RACSignal *deleteItemsAtIndexPathsSignal; // 请勿订阅此信号 diff --git a/LPDCollectionViewKit/Classes/LPDCollectionViewModel.h b/LPDCollectionViewKit/Classes/LPDCollectionViewModel.h index 1e267aa..c553ca2 100644 --- a/LPDCollectionViewKit/Classes/LPDCollectionViewModel.h +++ b/LPDCollectionViewKit/Classes/LPDCollectionViewModel.h @@ -15,6 +15,8 @@ NS_ASSUME_NONNULL_BEGIN @interface LPDCollectionViewModel : NSObject +@property (readonly, nonatomic, getter = getSections) NSArray *collectionViewModelSections; + + (instancetype) new NS_UNAVAILABLE; @end diff --git a/LPDCollectionViewKit/Classes/LPDCollectionViewModel.m b/LPDCollectionViewKit/Classes/LPDCollectionViewModel.m index cc56721..e19c75b 100644 --- a/LPDCollectionViewKit/Classes/LPDCollectionViewModel.m +++ b/LPDCollectionViewKit/Classes/LPDCollectionViewModel.m @@ -44,6 +44,7 @@ @interface LPDCollectionViewModel () @property (nonatomic, strong) LPDCollectionViewFactory *collectionViewFactory; @property (nonatomic, strong) RACSubject *reloadDataSubject; +@property (nonatomic, strong) RACSubject *scrollToItemAtIndexPathSubject; @property (nonatomic, strong) RACSubject *insertSectionsSubject; @property (nonatomic, strong) RACSubject *deleteSectionsSubject; @@ -76,6 +77,9 @@ @implementation LPDCollectionViewModel { id _dataSource; } +- (NSArray *)getSections { + return [NSArray arrayWithArray:_sections]; +} - (instancetype)init { if (self = [super init]) { @@ -176,6 +180,25 @@ - (NSInteger)sectionIndexForFooterViewModel:(__kindof id)cellViewModel { NSUInteger sectionIndex = self.sections.count > 0 ? self.sections.count - 1 : 0; [self addCellViewModel:cellViewModel toSection:sectionIndex]; @@ -554,6 +577,10 @@ - (void)replaceSectionWithCellViewModels:(NSArray<__kindof id)footerViewModelFromSection:(NSInteger)sectionIndex; +#pragma mark - scrollToItem methods + +- (void)scrollToCollectionItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated; + #pragma mark - add cells methods /**