Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it wrong to set viewModel as table views datasource?

I have seen many codes where set ViewModel as a table view data source, and many which don't.

1.Setting data source to the ViewModel some time makes sense as the data source methods mainly deal with the presentation logic.

2.On the other hand setting the ViewModel as the data source implies that you are implementing cellForRowAtIndexPath etc which makes it not independent of UIKit.

What is the best way to architecture your apps, Kindly clarify?

like image 295
Suhas Aithal Avatar asked Sep 27 '17 07:09

Suhas Aithal


1 Answers

The answer would be, there is no best way to architecture an app. There are many good ways to organize your classes according to your needs. Here is an example of how I organize my viewModel in order to show data in the table view:

PaymentSectionItem is my ViewModel

PaymentSectionItem.h

@interface PaymentSectionItem : NSObject

@property (assign, nonatomic) NSUInteger itemID;
@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSArray *elements;
@property (assign, nonatomic) kTransactionType transactionType;

+ (NSArray<PaymentSectionItem *> *)allSectionItemsWithData;

@end

PaymentSectionItem.m

@implementation PaymentSectionItem

#pragma mark - Custom Accessors

- (NSString *)localizedTitle {
    NSString *title = [NSString stringWithFormat:@"%@_section_title", self.name];
    return NSLocalizedString(title, @"Section title");
}

- (NSString *)localizedDescription {
    NSString *title = [NSString stringWithFormat:@"%@_section_description", self.name];
    return NSLocalizedString(title, @"Section description");
}

#pragma mark - Constructor

- (instancetype)initWithSectionItem:(kSectionItem)sectionItem {
    self = [super init];
    if (self) {
        [self setupFromHomeSectionItem:sectionItem];
    }
    return self;
}

#pragma mark - Private

- (void)setupFromHomeSectionItem:(kSectionItem)sectionItem {
    self.itemID = sectionItem;
    switch (sectionItem) {
        case kSectionItem1: {
            self.name = @"phones";
            self.elements = [Payment findPaymentsType1];
            break;
        }
        case kSectionItem2: {
            self.name = @"autopay";
            self.elements = [Payment findPaymentsType2];
            break;
        }
        case kSectionItem3: {
            self.name = @"trustfund";
            self.elements = [Payment findPaymentsType3];
            self.transactionType = kTransactionTypeTrustFund;
            break;
        }
        case kSectionItem4: {
            self.name = @"debitlink";
            self.elements = [Payment findPaymentsType4];
            self.transactionType = kTransactionTypeDebitLink;
            break;
        }
        case kSectionItem5: {
            self.name = @"pindebit";
            self.elements = [Payment findPaymentsType5];
            self.transactionType = kTransactionTypePINDebit;
            break;
        }
    }
}

#pragma mark - Public

+ (NSArray<PaymentSectionItem *> *)allSectionItemsWithData {
    NSMutableArray *items = [NSMutableArray new];
    [items addObject:[[PaymentSectionItem alloc] initWithSectionItem:kSectionItem1]];
    [items addObject:[[PaymentSectionItem alloc] initWithSectionItem:kSectionItem2]];
    [items addObject:[[PaymentSectionItem alloc] initWithSectionItem:kSectionItem3]];
    [items addObject:[[PaymentSectionItem alloc] initWithSectionItem:kSectionItem4]];
    [items addObject:[[PaymentSectionItem alloc] initWithSectionItem:kSectionItem5]];
    return items;
}

ViewController.h

- (void)viewDidLoad {
    [super viewDidLoad];
    self.items = [PaymentSectionItem allSectionItemsWithData];
}



#pragma mark - UITableViewDataSource

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return self.items.count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.items[section].elements.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    GTLAutoPaySectionItem *sectionItem = self.items[indexPath.section];
    NSString *identifier = [self identifierForSectionItem:sectionItem atIndex:indexPath];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    UITableViewCell<PaymentCellProtocol> *paymentCell = (UITableViewCell<PaymentCellProtocol> *)cell;
    [paymentCell setupCellFromValue:sectionItem.elements[indexPath.row] withSectionItem:sectionItem];
    return cell;
}

As you see, in my case I have a table view with many sections and each section has elements. That's exactly what I do in my ViewModel. Feel free to ask if you have any other question.

like image 63
carlos21 Avatar answered Sep 23 '22 22:09

carlos21