jollyCocoa jollyCocoa - 1 month ago 22
iOS Question

Can I make a UIPresentationController have userInteractionEnabled on PresentingViewController?

I am building a custom GUI on a universal app for iPhone and iPad. On iPad it relies heavily on "sideViews" for utilities like content manipulation, detailInformation and the like (think of an advanced SplitView). From a visual point of view the new UIPresentationController is spot on for letting me present these "sideViews" (and not using a dimmedView) and the implementation has been simple to build and maintain, while still integrate nicely with the storyboard. But I need to be able to manipulate the content of the presentingViewController while the presentedViewController is visible. So my question is, can I set userInteractionEnabled (or similar) on the presentingViewController while presenting the sideViews?

Answer

UIPresentationController inserts its container view as a window subview above the presenting view, thus any touches outside the presented view get trapped by the container view and never make it to the presenting view.

The fix is to insert a view on the container view that passes through touches to the presenting view. You can use this as a dimming view or set its backgroundColor to [UIColor clearColor] for a fully transparent view. Set the passthrough views in your presentation controller code.

@interface IVPasserView : UIView

@property (strong, nonatomic) NSArray* passthroughViews;

@end

@implementation IVPasserView

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    UIView* hit = [super hitTest:point withEvent:event];
    if (hit == self)
        for (UIView* passthroughView in _passthroughViews)
        {
            hit = [passthroughView hitTest:[self convertPoint:point toView:passthroughView]
                                 withEvent:event];
            if (hit)
                break;
        }
    return hit;
}

@end

Note: while this violates the spirit of -[UIView hitTest:withEvent:] in that it doesn't return a subview, this is in fact how the system standard UIPopoverPresentationController handles it. If you set the passthroughViews property there, the container view responds to hitTest:withEvent: with a passthrough view, even though they are not superview/subview! Thus it's likely to survive the next iOS release.