如何禁用iOS 11和iOS 12拖放是否加入WKWebView? [英] How to disable iOS 11 and iOS 12 Drag & Drop in WKWebView?

查看:121
本文介绍了如何禁用iOS 11和iOS 12拖放是否加入WKWebView?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在iOS 11和12上的 WKWebView 中长按图像或链接会启动拖放操作.删除会话(用户可以拖动图像或链接).如何禁用它?

Long-pressing images or links in a WKWebView on iOS 11 and 12 initiates a Drag & Drop session (the user can drag the image or the link). How can I disable that?

推荐答案

我确实找到了一个涉及方法混乱的解决方案但是也可以禁用WKWebView中的拖放操作而不会产生任何麻烦.

I did find a solution that involves method swizzling but it's also possible to disable drag and drop in a WKWebView without any swizzling.

注意:请参阅下面有关iOS 12.2+的特殊说明

WKContentView - WKWebView WKScrollView 的私有子视图-具有 interactions 属性,就像其他任何属性一样iOS 11+中的其他 UIView .该 interactions 属性包含一个 UIDragInteraction 和一个 UIDropInteraction .只需在 UIDragInteraction 上将 enabled 设置为 false 即可.

WKContentView — a private subview of WKWebView's WKScrollView — has an interactions property, just like any other UIView in iOS 11+. That interactions property contains both a UIDragInteraction and a UIDropInteraction. Simply setting enabled to false on the UIDragInteraction does the trick.

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

We don't want to access any private APIs and make the code as solid as possible.

假设您的 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;
                }
            }
        }
    }
}

就是这样!

上面的代码在iOS 12.2上仍然可以使用,但是何时调用它很重要.在iOS 12.1及更低版本上,您可以在创建 WKWebView 之后立即调用此代码.那不可能了. WKContentView interactions 数组在首次创建时为空.仅在将 WKWebView 添加到附加到 UIWindow 的视图层次结构中后填充-只需将其添加到尚未属于可见视图层次结构的超级视图中是不足够的.在视图控制器中, viewDidAppear 很可能是一个安全的调用位置.

The above code still works on iOS 12.2, but it is important when to call it. On iOS 12.1 and below you could call this code right after creating the WKWebView. That's not possible anymore. The WKContentView's interactions array is empty when it's first created. It is only populated after the WKWebView is added to a view hierarchy that is attached to a UIWindow - simply adding it to a superview that is not yet part of the visible view hierarchy is not enough. In a view controller viewDidAppear would most likely be a safe place to call it from.

  • 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]
  • The breakpoint was hit
  • I used lldb to print the backtrace using the bt command

这是输出:

* 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 

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

So clearly the creation and addition of the UIDragInteraction is triggered by the view moving to (being added to) a window.

这篇关于如何禁用iOS 11和iOS 12拖放是否加入WKWebView?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆