iOS应用多是通过多个UIViewController的跳转来展示多个界面,通常负责这一系列的是UINavigationController。
这样实现?
SomeViewController *someVC = [[SomeViewController alloc] init];
someVC.someID = 100;
[self.navigationController pushViewController:someVC animated:YES];
这样两个ViewController
之间个耦合关系就加大了,当前VC需要实例化下一个VC,并设置这个VC的一些属性,然后调用自己的navigationController
push。
![](/images/20150728/Screen Shot 2015-07-28 at 1.29.21 PM.png)
这样吧,把这些事情都交给navigationController
吧
UINavigationController+PushVCByName.h
@interface UINavigationController (PushVCByName)
- (void)pushViewControllerName:(NSString *)viewControllerName para:(NSDictionary *)para animated:(BOOL)animated;
- (void)pushViewControllerName:(NSString *)viewControllerName animated:(BOOL)animated;
@end
UINavigationController+PushVCByName.m
#import <objc/runtime.h>
@implementation UINavigationController (PushVCByName)
- (void)pushViewControllerName:(NSString *)viewControllerName para:(NSDictionary *)para animated:(BOOL)animated
{
const char *name = [viewControllerName UTF8String];
Class vcClass = objc_getClass(name);
if (vcClass != NULL) {
UIViewController *vc = [[vcClass alloc]init];
if (para != nil) {
[para enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSString *property = key;
[vc setValue:obj forKey:property];
}];
}
[self pushViewController:vc animated: animated];
}
}
- (void)pushViewControllerName:(NSString *)viewControllerName animated:(BOOL)animated
{
[self pushViewControllerName:viewControllerName para:nil animated:animated];
}
首先根据viewControllerName
利用runtime
得到Class
,然后利用KVO设置property,这样视图间的耦合关系就少了。
![](/images/20150728/Screen Shot 2015-07-28 at 1.30.35 PM.png)
当然情况没有这么简单,需要考虑的情况还有很多,这里只是一个思路.
首先就是KVO set value检查。
- (void)pushViewControllerName:(NSString *)viewControllerName para:(NSDictionary *)para animated:(BOOL)animated
{
const char *name = [viewControllerName UTF8String];
Class vcClass = objc_getClass(name);
if (vcClass != NULL) {
UIViewController *vc = [[vcClass alloc]init];
if (para != nil) {
[para enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSString *propertyName = key;
objc_property_t property = class_getProperty(vcClass, [propertyName UTF8String]);
if (property != NULL) {
[vc setValue:obj forKey:propertyName];
}else{
@throw [NSException exceptionWithName:@"UIViewController set Wrong property" reason:[NSString stringWithFormat:@"%@ don't have property %@", viewControllerName, propertyName] userInfo:nil];
}
}];
}
[self pushViewController:vc animated:YES];
}
}
在setValue:
前先检查Class是否有对应的属性名,没有则抛出异常。
还有
UIViewController
的init
方式有很多,是否需要加载视图文件(xib、storyboard),这也是要考虑在内的。