2017-09-27 73 views
10

我看过很多代码,其中将ViewModel设置为表视图数据源,许多代码没有。将viewModel设置为表视图数据源是错误的吗?

1.在一段时间内将数据源设置到ViewModel是有意义的,因为数据源方法主要处理表示逻辑。

2.另一方面,将ViewModel设置为数据源意味着您正在实施cellForRowAtIndexPath等,这使得它不独立于UIKit

什么是建筑你的应用程序的最佳方式,请澄清一下?

回答

3

答案是,没有最好的方式来构建应用程序。根据您的需求组织您的课程有很多好方法。 下面是我如何安排我的视图模型,以显示在表格视图中的数据为例:

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中所做的。随意问你是否有其他问题。

+0

我知道这个解决方案中,我一直在寻找 - 1,迅速解决2.对两难困境的回答“应该在哪里的cellForRowAtIndexPath:去?在vc或vm中,为什么? –

+1

我也知道解决方法,你在哪里编写获取行数的方法,表视图部分以及获取View Model内部单元配置数据并在VC中调用它们的方法。很有道理,但这不是一点儿矫枉过正?你真的不会减少你VC中的行数,而且苹果把“cellForRowAtIndexPath:”方法内部数据源中的od意味着它不完全属于视图层。希望你明白我的困境,我相信很多人也有这样的困境。 –

+0

@SuhasAithal:在辅助中减少行数,主要目标应该是使可读性,可理解性,可维护性等等。行数并不是说代码是错误的,它可以使其他人阅读代码。 –

1

否,将视图模型设置为数据源,充当数据模型是没有错误的。

那么,这本书说,保持M,V & C单独的可读性和可维护性。但是现在我们有了多种设计模式来保持简单。基本上,在模型中,我们只存储数据,而且它的操作是在视图级完成的,这是实现视图的好方法。

你不能总是有一个紧密耦合或松散耦合五,它取决于这两个的复杂性。

+0

让我等待其他有知识的人在接受任何答案之前回复。无论如何感谢您的回复。 –

0

视图模型

什么你的建议是没有错的。在我看来,视图模型只是简单的逻辑,就像字体和颜色一样。据我所知,没有人宣布这个规则,但我希望视图模型很简单。

在我看来,您的表格视图所在的位置应与您的模型无关。假设你的tableView的superview是一个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() 
    } 
    } 

    ... 
+0

嗨,如果视图模型只需要字体和颜色,我们不能实现使用Xcode运行时属性?或像pixate的东西?为什么你需要MVVM?正如我在评论Luzo的回答时所说的那样,这使得MVVM不适用于许多ios应用程序或与其相关。 –

+0

我没有说字体和颜色。如果您可以找到一种使用Xcode运行时属性分配字体的方法,那么请随意。这样做没有错。我不会认为视图模型只是一个子类。 Xcode运行时属性对我来说似乎也是一个视图模型。所以我不明白你关于MVVM的问题。 – 2017-10-09 07:03:26

+0

“我不认为视图模型只是一个子类”。哦好的。感谢您的回答。 –

相关问题