- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
这似乎是这里讨论最频繁的主题之一,但我找不到真正有效的解决方案。我发布这个问题是为了分享我发现的解决方案,并希望找到更好/更清洁的解决方案
情况描述:
我的应用中有一个UIWebview
webview中有文本输入/区域
长按文本区域/输入会弹出一个上下文菜单,其中包含“剪切”、“复制”、“定义”等。
我们需要在不禁用用户输入的情况下禁用此菜单。
到目前为止我尝试了什么(不起作用的东西):
此解决方案告诉我们将 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:
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/
我是一名优秀的程序员,十分优秀!