某些情况下,控制器下的view不能够直接和控制器来交互。比如在复杂的界面纯代码实现中,我们经常考虑的就是将视图分块,每一块用一个UIView封装,当着模块中的subView需要相应屏幕触摸操作并传导给控制器来进行跳转。又或者UITablView中cell的子试图需要和控制器进行交互的情况。
这种情况下用代理或者block显然很不好,view --(delegate、block)> parentView --(delegate、block)> ViewController,当然是可以实现,但是代码太多,并且并名是个问题,都是一样的目的,怎么给这些同样目的的方法命名呢。通知也是一个办法,但是也不是一个好办法,明明是一个模块并且纵向的结构,是不应该用通知来解决问题的。
这里可以用最简单的响应链遍历的方式,获取一个试图的当前所在的控制器:
#import <UIKit/UIKit.h>
@interface UIView (JKRViewController)
/// 当前视图最近一级的UIViewController
@property (nonatomic, strong, readonly) UIViewController *jkr_viewController;
@end
#import "UIView+JKRViewController.h"
@implementation UIView (JKRViewController)
- (UIViewController *)jkr_viewController {
UIResponder *next = [self nextResponder];
do {
if ([next isKindOfClass:[UIViewController class]]) {
return (UIViewController *)next;
}
next = [next nextResponder];
} while (next != nil);
return nil;
}
@end
这样,当需要获取一个UIView对象所在的控制器的时候,只需要调用self.jkr_viewController就可以了。比如在UITableView的cell中有一个UIImageView用来显示头像,点击头像需要跳转用户详情页的时候,只需要在UIImageView的touchesBegan方法中直接跳转就可以了:
[self.jkr_viewController presentViewController:userDetailViewController animated:YES completion:nil];
这样,在使用父子控制器、多层视图封装、列表视图的时候,就可以很方便的进行界面跳转的操作,避免过多的精力和时间思考在事件传递上面。
源码链接
网友评论