Search code examples
iphoneiosuiviewhittest

send touch event to UIviewController stacked in the back


In my app I have 2 transparent UIViewController layers. the first layer contain UIView object that i am trying to recognize by touch with:

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;

method.

the problem is, there is an transparent UIViewController above it.

I have tried to implement touch event on the SeconedStackedViewController and to create an instance of FirstStackedViewController and call the same method from there. the methods are called, but the hit test not.

Code:

FirstStackedViewController *fsvc = [[FirstStackedViewController alloc]init];


- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
      [fsvc hitTest:point withEvent:event];
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
      fsvc = [[FirstStackedViewController alloc]init];
      [fsvc touchesEnded:touches withEvent:event];
}

How can I override this method to be called on the FirstStackedViewController? if i will can simulate a touch on the FirstStackedViewController i think it will make the work


Solution

  • My first question is why you are pushing a transparent view controller. Might your needs be better served by layering a transparent view within the same controller?

    Without looking at your requirements, it's hard to say for sure, but most likely this is more in accord with the usual separation of logic: you have a need for code that can receive input from one view and pass it to other logic. It has need to know about the internals of both, and therefore is a good candidate for a controller object with the knowledge needed to accomplish your task.

    In this case, you would have no trouble at all - just present your transparent view, and pass touches to whatever action you wish.

    But there are good reasons to do a VC with a transparent view. To access the VC beneath you, you can as another responder said access the app delegate. I'd keep the app delegate out of it, and just access self.navController.viewControllers. This array represents the stack of VCs. Then iterate downward - the one 'below' you is the one you want to relay the message to.

    Most likely rather than using isMemberOfClass you'd want to define a protocol and check whether the VC conformsToProtocol.

    for (int i=0; i < navBar.viewControllers.count ; i++) {
       UIViewController *current = navBar.viewControllers[i];
       if (current == self) {
          UIViewController *targetVC = navBar.viewControllers[i+1]; // make sure you're not over bounds - you could do this in the loop def'n.
          if ([targetVC class] conformsToProtocol("TransparentPassingActions")]) {
             // pass message
          }
       }
    }
    

    You can also just use indexOfObject to get the current VC, I suppose, and then look one lower. That gets rid of the loop.

    The pseudo-code in the previous answer confuses UIViews and UIViewControllers, by the way; perhaps this was clear to you. It is not possible to access view controllers by accessing views.