iOS关于如何让<界面切换逻辑>与<数据业务逻辑>解耦的探讨
来源:互联网 发布:php 整数保留2位小数 编辑:程序博客网 时间:2024/06/06 14:12
在各种问答社区里面游荡的时候,经常会有人问到类似于:
怎么在tableviewcell里面点击一个button让uitableviewcontroller切换到另外一个controller呢?
其实这个问题遇到的情况很多,其实还是View与Controller的代码解藕的问题。
这篇博客只是以这个问题的解决为目的:
最早几年前接触iOS的时候用了一个当时很火的库:Three20 from facebook。但是随着编程思维的转变,发现这样的库有几个不好的地方:
1. 太过于重量级,什么功能都有
2. 自定义比较麻烦
3. 库内部的模块代码耦合太严重
所以我们后来花了很大的力气,把这个库完全去除。后来我们搭建iOS工程的基本是不会选择大型库的。典型的一个例子:AFNetworking VSMKNetworkKit 这个2个库我们选择的是MKNetworkKit,很显然后者更轻量级。AFNetworking做了很多其他的工作,比如:图片异步加载,但是显然这些工作会有更优秀的第三方库类似于SDWebImage 来完成。
再回到一开始的问题,这也是一个解藕的问题,那么我是怎么做的呢?解决方法来源于Three20的TTNavigator,我把他从Three20框架中剥离了出来,并同时优化了一下(不再是 url-base-navigation)。
直接上代码了:
JKNavigator.h
#import <Foundation/Foundation.h>/************************************************************************ * Dependencies: JKSingletonObject, JKViewController. * Based on: TTNavigator. ************************************************************************/#import "JKSingletonObject.h"@interface JKNavigator : JKSingletonObjectJK_SINGLETON_INSTANCE_METHOD_INTERFACE(JKNavigator)/** * The window that contains the view controller hierarchy. */@property (nonatomic, readonly) UIWindow *window;/** * The controller that is at the root of the view controller hierarchy. */@property (nonatomic, readonly) UIViewController* rootViewController;@property (nonatomic, readonly) UINavigationController* topNavigationController;/** * Removes all view controllers from the window and releases them. */- (void)removeAllViewControllers;/** * Register class. */- (void)registerNavigationSubclass:(Class)navigationSubclass;/*! * Set navigaiton controller view background color. */@property (nonatomic, strong) UIColor *navigationControllerBackgroundColor;/** * Push view controller in global navigator. * lightweight API for [Push & Present ViewController]. * I think it's more suitable than Url-based in Three20 for us. Here are some reasons: * => 1. APIs look like official APIs. * => 2. Easy to know the Class name without importing the header. * => 3. More controllable for us. */- (UIViewController *)pushViewController:(NSString *)classString animated:(BOOL)animated;- (UIViewController *)pushViewController:(NSString *)classString withQuery:(id)query animated:(BOOL)animated;- (UIViewController *)pushNibViewController:(NSString *)classString animated:(BOOL)animated;- (UIViewController *)pushNibViewController:(NSString *)classString withQuery:(id)query animated:(BOOL)animated;- (UIViewController *)presentViewController:(NSString *)classString animated:(BOOL)animated;- (UIViewController *)presentViewController:(NSString *)classString withQuery:(id)query animated:(BOOL)animated;- (UIViewController *)presentViewController:(NSString *)classString withQuery:(id)query animated:(BOOL)animated completion:(void(^)(void))completion;- (UIViewController *)presentNibViewController:(NSString *)classString animated:(BOOL)animated;- (UIViewController *)presentNibViewController:(NSString *)classString withQuery:(id)query animated:(BOOL)animated;- (UIViewController *)presentNibViewController:(NSString *)classString withQuery:(id)query animated:(BOOL)animated completion:(void(^)(void))completion;@end
JKNavigator.m
#import "JKNavigator.h"#import "JKViewController.h"@interface JKNavigator ()@property (nonatomic, strong) Class navigationSubclass;@end@implementation JKNavigator@synthesize navigationSubclass = _navigationSubclass;JK_SINGLETON_INSTANCE_METHOD_IMPL(JKNavigator)#pragma mark - Getter & Setter- (Class)navigationSubclass{ if (!_navigationSubclass) { _navigationSubclass = [UINavigationController class]; } return _navigationSubclass;}- (void)setNavigationSubclass:(Class)navigationSubclass{ if ([navigationSubclass isSubclassOfClass:[UINavigationController class]]) { _navigationSubclass = navigationSubclass; } else { @throw [NSException exceptionWithName:@"Incorrect Class" reason:@"You can only set UINavigationController subclass here." userInfo:@{}]; }}- (UIWindow *)window{ return [UIApplication sharedApplication].keyWindow;}- (UIViewController *)rootViewController{ return self.window.rootViewController;}- (UINavigationController *)topNavigationController{ UINavigationController *root = (UINavigationController *)self.rootViewController; while (root) { UINavigationController *child = (UINavigationController *)root.presentedViewController; if (child && [child isKindOfClass:[UINavigationController class]]) { root = child; } else { return root; } } return nil;}#pragma mark - Remove all.- (void)removeAllViewControllers{ UINavigationController *rootNavigator = (UINavigationController *)self.rootViewController; UINavigationController *root = (UINavigationController *)self.rootViewController; while (root) { if (root && [root isKindOfClass:[UINavigationController class]]) { [root dismissViewControllerAnimated:NO completion:NULL]; } root = (UINavigationController *)root.presentedViewController;; } [rootNavigator popToRootViewControllerAnimated:NO];}#pragma mark - Private methods- (UIViewController *)pushViewController:(NSString *)classString withNib:(BOOL)witNib withQuery:(id)query animated:(BOOL)animated{ return [self showViewControllerWithAction:@"Push" classString:classString withNib:witNib withQuery:query animated:animated completion:NULL];}- (UIViewController *)presentViewController:(NSString *)classString withNib:(BOOL)witNib withQuery:(id)query animated:(BOOL)animated completion:(void(^)(void))completion{ return [self showViewControllerWithAction:@"Present" classString:classString withNib:witNib withQuery:query animated:animated completion:completion];}- (UIViewController *)showViewControllerWithAction:(NSString *)action classString:(NSString *)classString withNib:(BOOL)witNib withQuery:(id)query animated:(BOOL)animated completion:(void(^)(void))completion{ UIViewController *controller = nil; UINavigationController *topNavigationController = [self topNavigationController]; // Generate UIViewController from classString. Class class = NSClassFromString(classString); if ([class isSubclassOfClass:[JKViewController class]]) { controller = witNib ? [[class alloc] initWithNibAndQuery:query] : [[class alloc] initWithQuery:query]; } else if ([class isSubclassOfClass:[UIViewController class]]) { controller = witNib ? [[class alloc] initWithNibName:classString bundle:nil] : [[class alloc] init]; } // Show controller. if (controller && topNavigationController) { if ([action isEqualToString:@"Push"]) { [topNavigationController pushViewController:controller animated:animated]; } else if ([action isEqualToString:@"Present"]) { if ([controller isKindOfClass:[UINavigationController class]]) { [topNavigationController presentViewController:controller animated:animated completion:completion]; } else { UINavigationController *navigation = [[self.navigationSubclass alloc] initWithRootViewController:controller]; navigation.view.backgroundColor = self.navigationControllerBackgroundColor; [topNavigationController presentViewController:navigation animated:animated completion:completion]; } } } return controller;}#pragma mark - Push methods- (void)registerNavigationSubclass:(Class)navigationSubclass;{ self.navigationSubclass = navigationSubclass;}#pragma mark- (UIViewController *)pushViewController:(NSString *)classString animated:(BOOL)animated{ return [self pushViewController:classString withNib:NO withQuery:nil animated:animated];}- (UIViewController *)pushViewController:(NSString *)classString withQuery:(id)query animated:(BOOL)animated{ return [self pushViewController:classString withNib:NO withQuery:query animated:animated];}- (UIViewController *)pushNibViewController:(NSString *)classString animated:(BOOL)animated{ return [self pushViewController:classString withNib:YES withQuery:nil animated:animated];}- (UIViewController *)pushNibViewController:(NSString *)classString withQuery:(id)query animated:(BOOL)animated{ return [self pushViewController:classString withNib:YES withQuery:query animated:animated];}#pragma mark- (UIViewController *)presentViewController:(NSString *)classString animated:(BOOL)animated{ return [self presentViewController:classString withNib:NO withQuery:nil animated:animated completion:NULL];}- (UIViewController *)presentViewController:(NSString *)classString withQuery:(id)query animated:(BOOL)animated{ return [self presentViewController:classString withNib:NO withQuery:query animated:animated completion:NULL];}- (UIViewController *)presentViewController:(NSString *)classString withQuery:(id)query animated:(BOOL)animated completion:(void(^)(void))completion{ return [self presentViewController:classString withNib:NO withQuery:query animated:animated completion:completion];}- (UIViewController *)presentNibViewController:(NSString *)classString animated:(BOOL)animated{ return [self presentViewController:classString withNib:YES withQuery:nil animated:animated completion:NULL];}- (UIViewController *)presentNibViewController:(NSString *)classString withQuery:(id)query animated:(BOOL)animated{ return [self presentViewController:classString withNib:YES withQuery:query animated:animated completion:NULL];}- (UIViewController *)presentNibViewController:(NSString *)classString withQuery:(id)query animated:(BOOL)animated completion:(void(^)(void))completion{ return [self presentViewController:classString withNib:YES withQuery:query animated:animated completion:completion];}@end
当然其中还部分牵扯到了其他的class,可以根据你的需求去除。JKNavigator是一个singleton object。使用时异常简单:
[[JKNavigator instance] pushViewController:@"YourViewControllerClassString" animated:YES];[[JKNavigator instance] pushNibViewController:@"YourViewControllerClassString" animated:YES];
不需要包含任何头文件,在任何地方都可以进行push操作。极大程序上解藕了View和Controller。
0 0
- iOS关于如何让<界面切换逻辑>与<数据业务逻辑>解耦的探讨
- PyQt5系列教程(六)如何让界面和逻辑分离
- PyQt5 如何让界面和逻辑分离简介
- 界面与逻辑的关系设计
- 关于二项逻辑斯谛回归的探讨
- 关于对js逻辑与逻辑或的理解
- 让activity的逻辑业务快速切换到fragment
- 校验业务与主逻辑解耦设计探讨与实践(观察者模式篇)
- 校验业务与主逻辑解耦设计探讨与实践(AOP篇)
- 关于WPF逻辑树深入探讨
- 逻辑与界面相分离
- MFC(0)关于MFC中的界面与业务逻辑的分离
- 关于时间的逻辑
- Delphi中实现界面与业务逻辑的分离
- MFC的 界面与逻辑分离(一)
- java重试工具库: 实现业务逻辑与重试逻辑的解耦
- Android 表单逻辑校验方案的探讨
- 领域逻辑与业务逻辑的关系
- iOS 开发系列:CoreData Object 变成 Fault 的一种方式
- Java的接口实现
- CString转char*
- vs xcode快捷键
- js 删除指定的元素。
- iOS关于如何让<界面切换逻辑>与<数据业务逻辑>解耦的探讨
- Thrift 操作 Hbase
- libgdx demo
- DedeCMS 友情链接按分类网站类型调用的方法
- TAR命令的基本使用方法详解
- unity3d math 常用的数学
- hdu4973(线段树)
- SpringMVC一次请求多次进入Control的原因
- poj 2983 差分约束