接上一篇文章说到使用ViewModel来瘦身ViewController,也就是把ViewController中有关原始数据适配到view需要的数据的一种办法.
- (void)onRoomInfoUpdateNotification:(NSNotification*)notification { MFChatRoomMessage* message = [[MFChatRoomMessage alloc] init]; message.msgType = kSystemType; message.msgSubType = kPlanTextSubType; MFRoomInfo* roomInfo = [[MFAppModel sharedObject].chatroomModelEx getCurrentRoomInfo]; NSNumber* isLock = [[notification userInfo] objectForKey:KChatRoomIsLockChangeKey]; NSNumber* isTopicChange = [[notification userInfo] objectForKey:KChatRoomIsTopicChangeKey]; if (isLock.unsignedIntegerValue == 1) { message.msgText = (roomInfo.locked ? @"房主将房间锁定" : @"房主将房间解锁了"); } else if (isTopicChange.unsignedIntegerValue == 1) { message.msgText = [NSString stringWithFormat:@"房主更改了话题 %@", roomInfo.subject]; } else { message.msgText = @"房主更改了房间信息"; } [self appendChatRoomMessage:message forceRefresh:YES]; }
截取上面一段代码仅供参考说明,这段代码实际上就干了一件事:
[self appendChatRoomMessage:message forceRefresh:YES];
把message传给appendChatRoomMessage进行后续的处理,而上面的若干行代码都是对message进行赋值,那最简单的想法就是能否通过一个方法可以直接获取到message,有了这样的想法,我们会定义这样的方法
+ (MFChatRoomMessage *)getChatRoomMessage:(NSNotification*)notification msgType:(MFChatRoomMsgType)msgType msgSubType:(MFChatRoomMsgSubType)msgSubType { MFChatRoomMessage* message = [[MFChatRoomMessage alloc] init]; message.msgType = kSystemType; message.msgSubType = kPlanTextSubType; MFRoomInfo* roomInfo = [[MFAppModel sharedObject].chatroomModelEx getCurrentRoomInfo]; NSNumber* isLock = [[notification userInfo] objectForKey:KChatRoomIsLockChangeKey]; NSNumber* isTopicChange = [[notification userInfo] objectForKey:KChatRoomIsTopicChangeKey]; if (isLock.unsignedIntegerValue == 1) { message.msgText = (roomInfo.locked ? @"房主将房间锁定" : @"房主将房间解锁了"); } else if (isTopicChange.unsignedIntegerValue == 1) { message.msgText = [NSString stringWithFormat:@"房主更改了话题 %@", roomInfo.subject]; } else { message.msgText = @"房主更改了房间信息"; } return message; }
那记下来ViewController里面只需要写
- (void)onRoomInfoUpdateNotification:(NSNotification*)notification { MFChatRoomMessage* message = [MyViewModel getChatRoomMessage:notification msgType:kSystemType msgSubType:kPlanTextSubType]; [self appendChatRoomMessage:message forceRefresh:YES]; }
这样就只要在VC里写两句话,而构造message的细节都封装在ViewModel里.
我们可能有很多像onRoomInfoUpdateNotification这样的回调,最终都要转换成MFChatRoomMessage, 那既然这类notification的作用只是对数据进行处理,和UI并没半毛钱关系,那就可以直接把这些全都封装到ViewModel里.接下来再看下我们的appendChatRoomMessage里面到底要干什么
- (void)appendChatRoomMessage:(MFChatRoomMessage *)message forceRefresh:(BOOL)forceRefresh { [_msgArray addObject:message]; if (_msgArray.count > 50) { [_msgArray removeObjectAtIndex:0]; } if (forceRefresh) { [self reloadAllMessage]; return; } }
把数据message加到一个数组,然后刷新UI,所以我们最终的目的还是刷UI,那实际上我们的ViewController连msgArray都不需要了,只要持有ViewModel就可以了
所以综上所述,MyViewModel应该是类似这样的
@interface MyViewModel : NSObject @property (nonatomic, strong) NSMutableArray *msgArray; - (void)addChatRoomMessage:(NSNotification*)notification msgType:(MFChatRoomMsgType)msgType msgSubType:(MFChatRoomMsgSubType)msgSubType; @end
@implementation - (NSMutableArray *)msgArray { if(_msgArray == nil) { _msgArray = [NSMutableArray array]; } return _msgArray; } - (MFChatRoomMessage *)getChatRoomMessage:(NSNotification*)notification msgType:(MFChatRoomMsgType)msgType msgSubType:(MFChatRoomMsgSubType)msgSubType { MFChatRoomMessage* message = [[MFChatRoomMessage alloc] init]; message.msgType = kSystemType; message.msgSubType = kPlanTextSubType; MFRoomInfo* roomInfo = [[MFAppModel sharedObject].chatroomModelEx getCurrentRoomInfo]; NSNumber* isLock = [[notification userInfo] objectForKey:KChatRoomIsLockChangeKey]; NSNumber* isTopicChange = [[notification userInfo] objectForKey:KChatRoomIsTopicChangeKey]; if (isLock.unsignedIntegerValue == 1) { message.msgText = (roomInfo.locked ? @"房主将房间锁定" : @"房主将房间解锁了"); } else if (isTopicChange.unsignedIntegerValue == 1) { message.msgText = [NSString stringWithFormat:@"房主更改了话题 %@", roomInfo.subject]; } else { message.msgText = @"房主更改了房间信息"; } return message; } - (void)addChatRoomMessage:(NSNotification*)notification msgType:(MFChatRoomMsgType)msgType msgSubType:(MFChatRoomMsgSubType)msgSubType { MFChatRoomMessage * message = [self getChatRoomMessage:notification msgType:msgType msgSubType:msgSubType]; [self.msgArray addObject:message]; } @end
然后在MyViewController里
@interface MyViewController : UIViewController @property (nonatomic, strong) MyViewModel *viewModel; @end
@implementation MyViewController - (MyViewModel *)viewModel { if(_viewModel == nil) { _viewModel = [[MyViewModel alloc] init]; } return _viewModel; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { return self.viewModel.msgArray[indexPath.row]; } - (void)onRoomInfoUpdateNotification:(NSNotification*)notification { [self.viewModel addChatRoomMessage:notification msgType:kSystemType msgSubType:kPlanTextSubType]; [self.tableView reload]; } @end
这里就进行了近一步的封装,把和数据msgArray的操作细节都封装到了VM,VC完全不用进行复杂的数据处理工作了.同样的想法,如果一个VC里面同一个table有很多Cell,也同样可以封装进VM,而VC只关心最后得到的cell,这样做会减少VC的大小,而可以更容易看明白VC的控制细节,而VM作为一个数据的转化工厂被VC持有,VC可以方便的取出View需要的最终数据.