Reputation: 4079
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
Upvotes: 3
Views: 3899
Reputation: 3629
I'd start by getting a refernce to the rootViewController. I'm assuming your hierarchy is root ->1st view controller --> 2nd view controller, then by initing fsvc you are creating a new instance and you are not actually getting the reference from the view hierarchy.
I'd recommend iterating through rootviewcontroller subviews and find your instance for first viewcontroller, then call the method on that instance.
//PSEUDO-Code for class names, but iteration should solve the problem.
if(UIView *view in RootViewController.subviews){
if(view isMemberOfClass: [FirstStackedViewController class]]){
[(FirstStackedViewController *)view touchesEnded:touches withEvent:event];
}
}
//ToolUser was right about mixing up VCs and regular Views, you'd want to do this:
for(UIViewController *vc in self.navigationController.viewControllers){
if(view isMemberOfClass: [FirstStackedViewController class]]){
[(FirstStackedViewController *)vc touchesEnded:touches withEvent:event];
}
}
Upvotes: 1
Reputation: 1542
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.
Upvotes: 2