WKWebview: UIDropInteraction is broken on iOS 12.2

Before iOS 12.2 we used the following code to implement our own handling for a UIDropInteraction. However, this functionality is broken on iOS 12.2, we no longer can find a view (or subview) of wkwebview where we can add our own UIDropInteraction.


UIView *dropInteractionContainingView = nil;
UIDropInteraction *defaultDropInteractionToRemove = nil;
for (UIView *subview in self.webview.scrollView.subviews) {
    for (id<UIInteraction> interaction in subview.interactions) {
        if ([interaction isKindOfClass:[UIDropInteraction class]]) {
            dropInteractionContainingView = subview;
            defaultDropInteractionToRemove = interaction;
            break;
        }
    }
}
        //on iOS 12.2 these two variables are always nil.
if (dropInteractionContainingView != nil && defaultDropInteractionToRemove != nil) {
    //Now we replace the existing unwanted uidropinteraction with our own, custom implementation.
    UIDropInteraction *customDropInteraction = [[UIDropInteraction alloc] initWithDelegate:self];
    [dropInteractionContainingView removeInteraction:defaultDropInteractionToRemove];
    [dropInteractionContainingView addInteraction:customDropInteraction];
}


Any ideas how to fix this in iOS 12.2?

Replies

This is a great question and I just debugged this myself. Here's what's different in iOS 12.2: The UIDragInteraction is only added _after_ the WKContentView is added to a _window_ (not just a superview).


Here's how I found it:

I searched through the WebKit source and found this: https://github.com/WebKit/webkit/blob/65619d485251a3ffd87b48ab29b342956f3dcdc7/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm#L4953

That's the method that creates and adds the UIDragInteraction. It turns out that this method (setupDataInteractionDelegates) actually exists on WKContentView. So I set a symbolic breakpoint on "-[WKContentView setupDataInteractionDelegates]". Sure enough that breakpoint was hit. I then displayed the backtrace in lldb:


(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 50.1
  * frame #0: 0x00000001115b726c WebKit`-[WKContentView(WKInteraction) setupDataInteractionDelegates]
    frame #1: 0x00000001115a8852 WebKit`-[WKContentView(WKInteraction) setupInteraction] + 1026
    frame #2: 0x00000001115a5155 WebKit`-[WKContentView didMoveToWindow] + 79


So we see that the interactions are only added AFTER the view is added to a view hierarchy that is attached to a window. Your old code should work, as long as you only call it after the WKWebView has been added to a window.


Johannes