如何在 WKWebView 中禁用 iOS 11 和 iOS 12 拖放?

Joh*_*rug 3 drag-and-drop ios wkwebview ios11

WKWebView在 iOS 11 和 12 上长按 a 中的图像或链接会启动拖放会话(用户可以拖动图像或链接)。我怎样才能禁用它?

Joh*_*rug 6

我确实找到了一个涉及方法调配解决方案,但也可以在 WKWebView 中禁用拖放而不进行任何调配。

注意:请参阅下面针对 iOS 12.2+ 的特别说明

WKContentViewWKWebView's的私有子视图WKScrollView— 有一个interactions属性,就像UIViewiOS 11+ 中的任何其他属性一样。该interactions属性同时包含 aUIDragInteraction和 a UIDropInteraction。只需设置enabledfalseon 即可UIDragInteraction

我们不想访问任何私有 API 并尽可能使代码可靠。

假设你WKWebView被称为webView

if (@available(iOS 11.0, *)) {        
    // Step 1: Find the WKScrollView - it's a subclass of UIScrollView
    UIView *webScrollView = nil;

    for (UIView *subview in webView.subviews) {
        if ([subview isKindOfClass:[UIScrollView class]]) {
            webScrollView = subview;
            break;
        }
    }

    if (webScrollView) {
        // Step 2: Find the WKContentView
        UIView *contentView = nil;

        // We don't want to trigger any private API usage warnings, so instead of checking
        // for the subview's type, we simply look for the one that has two "interactions" (drag and drop)
        for (UIView *subview in webScrollView.subviews) {
            if ([subview.interactions count] > 1) {
                contentView = subview;
                break;
            }
        }

        if (contentView) {
            // Step 3: Find and disable the drag interaction
            for (id<UIInteraction> interaction in contentView.interactions) {
                if ([interaction isKindOfClass:[UIDragInteraction class]]) {
                    ((UIDragInteraction *) interaction).enabled = NO;
                    break;
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

就是这样!

iOS 12.2+ 特别说明

上述代码在 iOS 12.2 上仍然有效,但何时调用它很重要。在 iOS 12.1 及更低版本上,您可以在创建WKWebView. 这已经不可能了。该WKContentViewinteractions它首次创建时数组为空。它仅在WKWebView添加到附加到的视图层次结构后才会填充UIWindow- 仅将其添加到尚不属于可见视图层次结构的超级视图是不够的。在视图控制器中viewDidAppear很可能是一个安全的地方来调用它。

我是怎么发现这个的?

这是输出:

* 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 
Run Code Online (Sandbox Code Playgroud)

很明显,UIDragInteraction视图的创建和添加是由移动到(被添加到)窗口的视图触发的。