- IRCollectionTableViewModel is a powerful MVVM Tableview/CollectionView for iOS, which is flexible and can easy to handle and reuse.
- MVVM structure.
- Flexible, Reusable.
- Git clone this project.
- Copy this project into your own project.
- Add the .xcodeproj into you project and link it as embed framework.
- You can remove the
demo
andScreenShots
folder.
- Add
pod 'IRCollectionTableViewModel'
in thePodfile
pod install
- Model--view--viewmodel (MVVM) is a software architectural pattern.
- It has advantages more than the tranditional MVC architectural. Can improve the whole code strurcture.
- More detail can see the MVVM wikipedia. MVVM
- Create a new class
TableViewViewModel
extendsTableViewBasicViewModel<UITableViewDataSource>
, and ImportIRCollectionTableViewModel
#import <IRCollectionTableViewModel/IRCollectionTableViewModel.h>
@interface TableViewViewModel : TableViewBasicViewModel<UITableViewDataSource>
@end
- You can add your init method and register the cell inside
- (instancetype)initWithTableView:(UITableView*)tableView;
...
- (instancetype)initWithTableView:(UITableView *)tableView {
if (self = [super init]) {
items = [[NSMutableArray<id<SectionModelItem>> alloc] init];
[tableView registerNib:[UINib nibWithNibName:CELL_NIB_NAME bundle:nil] forCellReuseIdentifier:CELL_IDENTIFIER];
}
return self;
}
- Add
update
method
- (void)update;
...
- (void)update {
[items removeAllObjects];
// Setup items
// [self setupRows];
}
- For setup
items
, other words, setup the sections/rows you want to show. CreateTableViewSectionItem
andTableViewRowItem
,DemoSectionType
,DemoRowType
typedef NS_ENUM(NSInteger, DemoSectionType){
DemoSection
};
typedef NS_ENUM(NSInteger, DemoRowType){
RowType_DemoRow
};
@interface TableViewRowItem : RowBasicModelItem
@property (readonly) DemoRowType type;
@end
@interface TableViewSectionItem : SectionBasicModelItem
@property (nonatomic) NSString* sectionTitle;
@property (nonatomic) SectionType type;
@end
- Implementation
TableViewSectionItem
andTableViewRowItem
in theTableViewViewModel.m
@implementation TableViewRowItem
@dynamic type;
@end
@implementation TableViewSectionItem
@end
- Setup
items
- (void)setupRows {
NSMutableArray *rowItems = [NSMutableArray array];
[rowItems addObject:[[TableViewRowItem alloc] initWithType:RowType_DemoRow withTitle:@"Demo Row"]];
[rowItems addObject:[[TableViewRowItem alloc] initWithType:RowType_DemoRow withTitle:@"Demo Row"]];
NSArray *demoRowItems = [NSArray arrayWithArray:rowItems];
TableViewSectionItem *item = [[TableViewSectionItem alloc] initWithRowCount:[demoRowItems count]];
item.type = DemoSection;
item.sectionTitle = @"Demo Section";
item.rows = demoRowItems;
[items addObject:item];
}
- Override
UITableViewDataSource
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return items.count;
}
- (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [items[section] rowCount];
}
- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
id<SectionModelItem> item = [items objectAtIndex:indexPath.section];
TableViewRowItem *row = (TableViewRowItem *)[item.rows objectAtIndex:[indexPath row]];
switch (item.type) {
case DemoSection:
{
switch (row.type) {
case RowType_DemoRow:
{
TableViewCell *cell = (TableViewCell *)[tableView dequeueReusableCellWithIdentifier:TableViewCell.identifier forIndexPath:indexPath];
cell.titleLabel.text = [NSString stringWithFormat:@"%@%ld", row.title, row.tagRange.location];
cell.editTextField.text = [editedTexts objectAtIndex:indexPath.row];
cell.editTextField.tag = row.tagRange.location;
cell.editTextField.delegate = self;
return cell;
}
}
break;
}
default:
break;
}
return [[UITableViewCell alloc] init];
}
- Use your view model
TableViewViewModel
#import "TableViewViewModel.h"
@implementation TableViewController {
TableViewViewModel *viewModel;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerNib:[UINib nibWithNibName:HEADER_VIEW_NIB_NAME bundle:nil] forHeaderFooterViewReuseIdentifier:HEADER_VIEW_IDENTIFIER];
viewModel = [[TableViewViewModel alloc] initWithTableView:_tableView];
_tableView.dataSource = viewModel;
[viewModel update];
}
@end
-
Just the same way of
TableViewViewModel
. Create a new classCustomCollectionViewModel
extendsTableViewBasicViewModel<UICollectionViewDataSource>
, and Import thisCustomCollectionViewModel
to view controller -
You can add your init method and register the cell inside
-
For setup
items
, other words, setup the sections/rows you want to show. CreateCustomCollectionSectionItem
andCustomCollectionRowItem
,CustomCollectionSectionType
-
Override
UICollectionViewDataSource
TableViewBasicViewModel
provides some usage methods
- (NSInteger)getRowTypeWith:(SectionType)type row:(NSInteger)row;
- (NSString *)getSectionTitleinSection:(NSInteger)section;
- (UIImage *)getSectionLeftIconinSection:(NSInteger)section;
- (SectionType)getSectionTypeinSection:(NSInteger)section;
- (void)hideRows:(BOOL)hide inSection:(NSInteger)section;
- (BOOL)hiddenRowsinSection:(NSInteger)section;
- (NSIndexSet *)getIndexSetWithSectionType:(SectionType)sectionType;
- (NSIndexPath *)getIndexPathWithSectionType:(SectionType)sectionType rowType:(RowType)rowType;
- (void)setupRowTag;
- (NSIndexPath *)getIndexPathFromRowTag:(NSInteger)rowTag;
-
Because the cells have reuse feature, somtimes we need to tag the cell/componenst if want to recognize the specific cell/components, thus
IRCollectionTableViewModel
provides a tag feature -
Setup tags by
setupRowTag
, it save the tag information in thetagRange
which is in theRowBasicModelItem
- (void)setupRows {
...
[self setupRowTag];
}
- Get tag
TableViewRowItem *row = (TableViewRowItem *)[item.rows objectAtIndex:[indexPath row]];
tag = row.tagRange.location;
- Get indexPath by tag
- (NSIndexPath *)getIndexPathFromRowTag:(NSInteger)rowTag;
- Sometimes you want to tag the UI components like
UITextField
, usesetTagRangeLength
TableViewRowItem *row = [[TableViewRowItem alloc] initWithType:RowType_DemoRow withTitle:@"Demo Row"];
[row setTagRangeLength:2];
...
[self setupRowTag];
- Then get tags
TableViewRowItem *row = (TableViewRowItem *)[item.rows objectAtIndex:[indexPath row]];
tag1 = row.tagRange.location;
tag2 = row.tagRange.location + 1;
cell.textField1.tag = tag1;
cell.textField2.tag = tag2;
- The tags are mapping to the same index path
[self getIndexPathFromRowTag:tag1] == [self getIndexPathFromRowTag:tag2]
Now, you can easy to tag anyhing you want.
- Hide rows for specific setion by
(void)hideRows:(BOOL)hide inSection:(NSInteger)section
- (NSInteger)getRowTypeWith:(SectionType)type row:(NSInteger)row;
- Get section title which set in the
SectionBasicModelItem
- (NSString *)getSectionTitleinSection:(NSInteger)section;
- Get section icon which set in the
SectionBasicModelItem
- (UIImage *)getSectionLeftIconinSection:(NSInteger)section;
- Get section type by section index
- (SectionType)getSectionTypeinSection:(NSInteger)section;
- Hide rows for specific setion by
(void)hideRows:(BOOL)hide inSection:(NSInteger)section
- Check hidden status by
(BOOL)hiddenRowsinSection:(NSInteger)section
- (void)hideRows:(BOOL)hide inSection:(NSInteger)section;
- (BOOL)hiddenRowsinSection:(NSInteger)section;
- Get index of section by section type
- (NSIndexSet *)getIndexSetWithSectionType:(SectionType)sectionType;
- Get index path by section type and row type
- (NSIndexPath *)getIndexPathWithSectionType:(SectionType)sectionType rowType:(RowType)rowType;
TableView | CollectionView |
---|---|