2017-09-27 38 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

「我不認爲視圖模型只是一個子類」。哦好的。感謝您的回答。 –

相關問題