Неправильно ли устанавливать viewModel в качестве источника данных таблиц?

Я видел много кодов, где установлен ViewModel в качестве источника данных табличного представления, а многие из них не работают.

1.Удаление источника данных в ViewModel имеет некоторое значение, поскольку методы источника данных в основном касаются логики представления.

2. С другой стороны, установка ViewModel в качестве источника данных означает, что вы реализуете cellForRowAtIndexPath и т.д., что делает его не независимым от UIKit.

Каков наилучший способ для архитектуры ваших приложений? Просьба уточнить?

Ответ 1

Ответ будет: нет лучшего способа для архитектуры приложения. Есть много хороших способов организовать ваши занятия в соответствии с вашими потребностями. Вот пример того, как я упорядочиваю свою модель viewModel для отображения данных в представлении таблицы:

PaymentSectionItem - это моя 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;
}

Как вы видите, в моем случае у меня есть табличное представление со многими разделами, и каждый раздел имеет элементы. Это то, что я делаю в своей модели ViewModel. Не стесняйтесь спрашивать, есть ли у вас другие вопросы.

Ответ 2

НЕТ, неверно устанавливать модель представления в качестве источника данных, действуя как модель данных.

Хорошо, в книге говорится: сохраняйте M, V и C раздельными для удобочитаемости и ремонтопригодности. Но теперь у нас есть несколько шаблонов дизайна, которые упрощают работу. В основном в модели мы сохраняем только данные, а их манипуляции выполняются на уровне представления, что является хорошим способом достижения представления.

Вы не всегда можете иметь плотно соединенные или слабо связанные M и V. Это зависит от сложности этих двух.

Ответ 3

ViewModel

То, что вы предлагаете, не так. На мой взгляд, модель представления - это только тривиальная логика, например, шрифты и цвета. Насколько мне известно, никто не объявил для этого правила, но я ожидал бы, что модель представления будет простой.

Если ваш табличный вид расположен, по моему мнению, не имеет отношения к вашей модели. Скажем, супервизор вашего tableView был UITableViewCell. В этом случае я бы подключил логику через обратные вызовы.

Таким образом, обратный вызов будет таким.

protocol EventTableViewCellDatasource: class {
  func showTimesTableViewDatasource() -> UITableViewDataSource
}

И камера будет делать это

class EventTableViewCell: UITableViewCell {

  weak var datasource: EventTableViewCellDatasource?

  @IBOutlet weak private var tableView: ShowTimesTableView! {
    didSet {
      tableView.dataSource = datasource?.showTimesTableViewDatasource()
    }
  }

  ...