IOS开发中响应者链

在IOS开发中,有时候会遇到如下情况:在页面1上有一个RedView,在RedView上有一个GreenView,在GreenView上有一个button,这些view的创建代码如下:

1、AppDelegate.m

 1 //
 2 //  AppDelegate.m
 3 //  响应者链
 4 //
 5 //  Created by mac on 16/5/10.
 6 //  Copyright © 2016年 mzw. All rights reserved.
 7 //
 8 
 9 #import "AppDelegate.h"
10 #import "RootViewController.h"
11 
12 @interface AppDelegate ()
13 
14 @end
15 
16 @implementation AppDelegate
17 
18 
19 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
20    
21     
22     self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
23     self.window.backgroundColor = [UIColor lightGrayColor];
24     [self.window makeKeyAndVisible];
25     
26     
27     RootViewController *rootVC = [[RootViewController alloc]init];
28     UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:rootVC];
29     self.window.rootViewController = nav;
30 
31     return YES;
32 }
33 
34 @end

2、RootViewController.m

 1 //
 2 //  RootViewController.m
 3 //  响应者链
 4 //
 5 //  Created by mac on 16/5/10.
 6 //  Copyright © 2016年 mzw. All rights reserved.
 7 //
 8 
 9 #import "RootViewController.h"
10 #import "FirstVCViewController.h"
11 #import "RedView.h"
12 
13 @interface RootViewController ()
14 
15 @end
16 
17 @implementation RootViewController
18 
19 - (void)viewDidLoad {
20     [super viewDidLoad];
21     self.view.backgroundColor = [UIColor grayColor];
22     RedView *redVC = [[RedView alloc]initWithFrame:CGRectMake(80, 80, 200, 200)];
23     [self.view addSubview:redVC];
24     
25 }
26 
27 @end

3、RedView.m

 1 //
 2 //  RedView.m
 3 //  响应者链
 4 //
 5 //  Created by mac on 16/5/10.
 6 //  Copyright © 2016年 mzw. All rights reserved.
 7 //
 8 
 9 #import "RedView.h"
10 #import "GreenView.h"
11 
12 @implementation RedView
13 
14 -(instancetype)initWithFrame:(CGRect)frame{
15     self = [super initWithFrame:frame];
16     if (self) {
17         self.backgroundColor = [UIColor redColor];
18         GreenView *grennView = [[GreenView alloc]initWithFrame:CGRectMake(50 , 50, 100,100)];
19         [self addSubview:grennView];
20         
21     }
22     return self;
23 }
24 
25 @end

4、GreenView.m

 1 //
 2 //  GreenView.m
 3 //  响应者链
 4 //
 5 //  Created by mac on 16/5/10.
 6 //  Copyright © 2016年 mzw. All rights reserved.
 7 //
 8 
 9 #import "GreenView.h"
10 #import "FirstVCViewController.h"
11 #import "UIView+ViewController.h"
12 
13 @implementation GreenView
14 
15 -(instancetype)initWithFrame:(CGRect)frame{
16     
17     self = [super initWithFrame:frame];
18     if (self) {
19         self.backgroundColor = [UIColor greenColor];
20         UIButton *myBtn = [[UIButton alloc]initWithFrame:CGRectMake(10, 10, 80, 40)];
21         myBtn.backgroundColor = [UIColor orangeColor];
22         [myBtn setTitle:@"导航按钮" forState:UIControlStateNormal];
23         [myBtn addTarget:self action:@selector(myBtnAction:) forControlEvents:UIControlEventTouchUpInside];
24         [self addSubview:myBtn];
25     }
26     
27     return  self;
28 }
29 
30 
31 -(void)myBtnAction :(UIButton*)sender{
32     
33     FirstVCViewController *firstVC = [[FirstVCViewController alloc]init];
34     [self.viewController.navigationController pushViewController:firstVC animated:YES];
35 
36 }
37 
38 @end

这时候我们想在GreenView.m中实现点击myBtn之后跳转到FirstVCViewController的实体firstVC,但发现其实我们写不了第34行,因为在myBtnAction方法中,self指的是GreenView的实例,而GreenView的实例greenView是没有.navigationController方法的,这就需要通过View的从属关系去找到grennView的响应者redView,然后找到redView的响应者RootVC。RootVC才有.navigationController的方法,这样就可以实现点击按钮跳转到另一个ViewController了。实现方式如下,给UIView使用Category扩展一个方法,方法名字叫viewController,也就是找一个UIView对象的所属的ViewController对象,viewController类别实现如下:

1、UIView+ViewController.h中:

 1 //
 2 //  UIView+ViewController.h
 3 //  Project-WXWeibo26
 4 //
 5 //  Created by keyzhang on 14-9-29.
 6 //  Copyright (c) 2014年 keyzhang. All rights reserved.
 7 //
 8 
 9 #import <UIKit/UIKit.h>
10 
11 @interface UIView (ViewController)
12 
13 - (UIViewController *)viewController;
14 
15 @end

 2、UIView+ViewController.m中:

 1 //
 2 //  UIView+ViewController.m
 3 //  Project-WXWeibo26
 4 //
 5 //  Created by keyzhang on 14-9-29.
 6 //  Copyright (c) 2014年 keyzhang. All rights reserved.
 7 //
 8 
 9 #import "UIView+ViewController.h"
10 
11 @implementation UIView (ViewController)
12 
13 - (UIViewController *)viewController
14 {
15     UIResponder *next = self.nextResponder;
16     do {
17         if ([next isKindOfClass:[UIViewController class]]) {
18             return (UIViewController *)next;
19         }
20         
21         next = next.nextResponder;
22     } while (next != nil);
23     
24     return nil;
25 }
26 
27 @end

 方法的核心就是去判断一个UIView对象的响应者所属的类是不是UIViewController类,如果不是的话就继续找它的响应者的响应者,直到找到响应者是UIViewController为止。

原文地址:https://www.cnblogs.com/jiwangbujiu/p/5479038.html