通常情况下,视图层只是简单负责数据展示和负责将事件响应转交给控制器C层执行,创建视图的代码都在控制器层中完成,因此V层的状态也不见得比M好得多。比如当我自定义一个扇形展开的菜单视图,在点击时的响应:
//LXDMenuView.m
- (void)clickMenuItem: (LXDMenuItem *)menuItem {
if ([_delegate respondsToSelector: @selector(menuView:didSelectedItem:)]) {
[_delegate menuView: self didSelectedItem: menuItem.tag];
}
}
//ViewController.m
- (void)menuView: (LXDMenuView *)menuView didSelectedItem: (NSInteger)index {
Class controllerCls = NSClassFromString(_controllerNames[index]);
UIViewController *nextController = [[controllerCls alloc] init];
[self.navigationController pushViewController: nextController animated: YES];
}这段代码是最常见的视图->控制器事件处理流程,当一个控制器界面的自定义视图、控件响应事件过多的时候,即便我们已经使用#pragma mark -的方式将这些事件进行分段,但还是会占用过大的代码量。MVC公认的问题是C完成了太多的业务逻辑,导致过胖,跟M层的处理一样的,笔者同样将一部分弱业务转移到V层上,比如上面的这段页面跳转:
@interface LXDMenuView: UIView
@property (nonatomic, strong) NSArray<NSString *> * itemControllerNames;
@end
@implementation LXDMenuView
- (void)clickMenuItem: (LXDMenuItem *)menuItem {
UIViewController *currentController = [self currentController];
if (currentController == nil) { return; }
Class controllerCls = NSClassFromString(_itemControllerNames[menuItem.tag]);
UIViewController *nextController = [[controllerCls alloc] init];
if ([currentController respondsToSelector: @selector(menuView:transitionToController:)]) {
[currentController menuView: self transitionToController: nextController];
}
[currentController.navigationController pushViewController: nextController animated: YES];
}
- (UIViewController *)currentController {
UIResponder *nextResponder = self.nextResponder;
while (![nextResponder isKindOfClass: [UIWindow class]]) {
if ([nextResponder isKindOfClass: [UIViewController class]]) {
return (UIViewController *)nextResponder;
}
nextResponder = nextResponder.nextResponder;
}
return nil;
}
@end这种业务转移的思路来自于开发中的Self-Manager模式一文。在这种代码结构中,如果V层决定了控制器接下来的跳转,那么可以考虑将跳转的业务迁移到V中执行。通过事件链查找的方式获取所在的控制器,这一过程并不能说违背了MVC的访问限制原则,在整个过程中V不在乎其所在的currentController和nextController的具体类型,通过自定义一个协议来在跳转前将nextController发送给当前控制器完成跳转前的配置。
这里要注意的是,Self-Manager有其特定的使用场景。当视图层的回调处理需要两层或者更多的时候,Self-Manager能有效的执行
如果抽离的足够高级,甚至可以定义一个同一个的Self-Manager协议来提供给自定义视图完成这些工作。这样同一套业务逻辑可以给任意的自定义视图复用,只要其符合视图<->控制器的捆绑关系。:
@protocol LXDViewSelfManager <NSObject> @optional - (void)customView: (UIView *)customView transitionToController: (UIViewController *)nextController; @end
- 上一篇:3.I/O操作
- 下一篇:5.视图层的动画效果
- 文章导航