Sha*_* RC 4 contextmenu objective-c uiwebview cordova
这似乎是这里最常讨论的主题之一,但我找不到真正有效的解决方案.我发布这个问题是为了分享我找到的解决方案以及希望找到更好/更清洁的解决方案
情况描述:
我的应用程序中有一个UIWebview
webview中有文本输入/区域
长按文本区域/输入会显示上下文菜单,其中包含"剪切","复制","定义"等.
我们需要在不禁用用户输入的情况下禁用此菜单.
到目前为止我尝试过的东西(东西不起作用):
此解决方案告诉我们要添加canPerformAction:withSender:到UIWebview的子类或UIWebview的委托中.
- (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];
}
Run Code Online (Sandbox Code Playgroud)
不起作用,因为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);
}
Run Code Online (Sandbox Code Playgroud)
这适用于图像和超链接,但不适用于输入.:(
第一个解决方案不起作用的根本原因是调用的子视图UIWebBrowserView.这似乎是一个视图,其canPerformAction为action上下文菜单中显示的任何内容返回true .
由于这UIWebBrowserView是一个私有类,我们不应该尝试将其子类化(因为它会让你的应用程序被拒绝).
所以我们做的是我们制作另一种方法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];
}
}
Run Code Online (Sandbox Code Playgroud)
并添加另一个方法来替换canPerformAction:withSender:with 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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
最后在ViewController的viewDidLoad中调用它:
[self replaceUIWebBrowserView:self.webView];
Run Code Online (Sandbox Code Playgroud)
注意:添加#import <objc/runtime.h>到viewController然后将不显示错误(方法).
注意:我正在使用NSSelectorFromString方法来避免在审核过程中检测到私有API选择器.
这似乎在iOS7中使用Xcode 5正常工作,如果有人能在此找到任何问题,请告诉我如何改进它..
| 归档时间: |
|
| 查看次数: |
2103 次 |
| 最近记录: |