How to inspect the responder chain?

前端 未结 6 1255
甜味超标
甜味超标 2020-12-08 10:51

I\'m doing some crazy multiple documents inside a single window stuff with the document-based architecture and I\'m 95% done.

I have this two-tier document architect

相关标签:
6条回答
  • 2020-12-08 11:18

    You can also add a category to class UIResponder with appropriate method that is possible to be used by any subclass of UIResponder.

    @interface UIResponder (Inspect)
    
    - (void)inspectResponderChain; // show responder chain including self
    
    @end
    
    @implementation UIResponder (Inspect)
    
    - (void)inspectResponderChain  
    {
        UIResponder *x = self;
        do {
            NSLog(@"%@", x);
        }while ((x = [x nextResponder]));
    }
    @end
    

    Than you can use this method somewhere in code as the example below:

    - (void)viewDidLoad {
        ...
        UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
        [self.view addSubview:myView];
        [myView inspectResponderChain]; // UIView is a subclass of UIResponder
        ...
    }
    
    0 讨论(0)
  • 2020-12-08 11:19

    Here is another version for Swift users:

    func printResponderChain(_ responder: UIResponder?) {
        guard let responder = responder else { return; }
    
        print(responder)
        printResponderChain(responder.next)
    }
    

    Simply call it with self to print out the responder chain starting from self.

    printResponderChain(self)
    
    0 讨论(0)
  • 2020-12-08 11:21

    Swift:

    extension UIResponder {
        var responderChain: [UIResponder] {
            var chain = [UIResponder]()
            var nextResponder = next
            while nextResponder != nil {
                chain.append(nextResponder!)
                nextResponder = nextResponder?.next
            }
            return chain
        }
    }
    
    // ...
    
    print(self.responderChain)
    
    0 讨论(0)
  • 2020-12-08 11:27

    You can iterate over the responder chain using the nextResponder method of NSResponder. For your example, you should be able to start with the current view, and then repeatedly print out the result of calling it in a loop like this:

    NSResponder *responder = currentView;
    while ((responder = [responder nextResponder])) {
         NSLog(@"%@", responder);
    }
    
    0 讨论(0)
  • 2020-12-08 11:36

    I'll improve a bit on the Responder category answer, by using a class method which feels more "useable" when debugging (you don't need to break in a specific view or whatever).

    Code is for Cocoa but should be easily portable to UIKit.

    @interface NSResponder (Inspect)
    
    + (void)inspectResponderChain;
    
    @end
    
    @implementation NSResponder (Inspect)
    
    + (void)inspectResponderChain
    {
      NSWindow *mainWindow = [NSApplication sharedApplication].mainWindow;
    
      NSLog(@"Responder chain:");
      NSResponder *responder = mainWindow.firstResponder;
      do
      {
        NSLog(@"\t%@", [responder debugDescription]);
      }
      while ((responder = [responder nextResponder]));
    }
    
    @end
    
    0 讨论(0)
  • 2020-12-08 11:39

    Here is the simplest one

        extension UIResponder {
            func responderChain() -> String {
                guard let next = next else {
                    return String(describing: self)
                }
    
                return String(describing: self) + " -> " + next.responderChain()
            }
        }
    
        // ...
    
        print(self.responderChain())
    
    0 讨论(0)
提交回复
热议问题