gpt4 book ai didi

objective-c - 在文本区域/输入 UIWebview 中禁用长按菜单

转载 作者:太空狗 更新时间:2023-10-30 03:59:23 25 4
gpt4 key购买 nike

这似乎是这里讨论最频繁的主题之一,但我找不到真正有效的解决方案。我发布这个问题是为了分享我发现的解决方案,并希望找到更好/更清洁的解决方案

情况描述:

  • 我的应用中有一个UIWebview

  • webview中有文本输入/区域

  • 长按文本区域/输入会弹出一个上下文菜单,其中包含“剪切”、“复制”、“定义”等。

我们需要在不禁用用户输入的情况下禁用此菜单。


到目前为止我尝试了什么(不起作用的东西):

覆盖canPerformAction

此解决方案告诉我们将 canPerformAction:withSender: 添加到 UIWebview 的子类或 UIWebview 的委托(delegate)中。

- (BOOL) canPerformAction:(SEL)action withSender:(id)sender
{
if (action == @selector(defineSelection:))
{
return NO;
}
else if (action == @selector(translateSelection:))
{
return NO;
}
else if (action == @selector(copy:))
{
return NO;
}

return [super canPerformAction:action withSender:sender];
}

不起作用,因为此类中的 canPerformAction: 不会为显示的菜单项调用。由于 sharedMenuController 与 Responder 链中的第一个响应者交互,因此在容器中实现 canPerformAction 会跳过 select 和 selectAll,因为它们已经被子菜单处理过。

操纵 CSS

将以下内容添加到 CSS:

html {
-webkit-user-select: none;
-webkit-touch-callout: none;
-webkit-tap-highlight-color:rgba(0,0,0,0);
}

这确实适用于图像和超链接但不适用于输入。:(

最佳答案

第一个解决方案不起作用的根本原因是名为 UIWebBrowserView 的 subview .这似乎是其 canPerformAction 对任何 action 返回 true 的 View 。显示在上下文菜单中。

自此 UIWebBrowserView是一个私有(private)类,我们不应该尝试对其进行子类化(因为它会使您的应用程序被拒绝)。

所以我们要做的是创建另一个名为 mightPerformAction:withSender: 的方法, 像这样-

- (BOOL)mightPerformAction:(SEL)action withSender:(id)sender {


NSLog(@"******Action!! %@******",NSStringFromSelector(action));


if (action == @selector(copy:))
{
NSLog(@"Copy Selector");
return NO;
}
else if (action == @selector(cut:))
{
NSLog(@"cut Selector");
return NO;
}
else if (action == NSSelectorFromString(@"_define:"))
{
NSLog(@"define Selector");
return NO;
}
else if (action == @selector(paste:))
{
NSLog(@"paste Selector");
return NO;
}
else
{
return [super canPerformAction:action withSender:sender];
}


}

并添加另一个方法来替换 canPerformAction:withSender: 为 mightPerformAction:withSender:

- (void) replaceUIWebBrowserView: (UIView *)view
{

//Iterate through subviews recursively looking for UIWebBrowserView
for (UIView *sub in view.subviews) {
[self replaceUIWebBrowserView:sub];
if ([NSStringFromClass([sub class]) isEqualToString:@"UIWebBrowserView"]) {

Class class = sub.class;

SEL originalSelector = @selector(canPerformAction:withSender:);
SEL swizzledSelector = @selector(mightPerformAction:withSender:);

Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(self.class, swizzledSelector);

//add the method mightPerformAction:withSender: to UIWebBrowserView
BOOL didAddMethod =
class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
//replace canPerformAction:withSender: with mightPerformAction:withSender:
if (didAddMethod) {
class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));

} else {

method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
}
}

最后在 ViewController 的 viewDidLoad 中调用它:

[self replaceUIWebBrowserView:self.webView];

注:添加#import <objc/runtime.h>到您的 viewController 然后 error(Method) 将不会显示。

注意:我正在使用 NSSelectorFromString避免在审核过程中检测到私有(private) API 选择器的方法。

关于objective-c - 在文本区域/输入 UIWebview 中禁用长按菜单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25263687/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com