Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone UIWebView-在<;img>;标签_Iphone_Ios_Ios4_Uiwebview - Fatal编程技术网

Iphone UIWebView-在<;img>;标签

Iphone UIWebView-在<;img>;标签,iphone,ios,ios4,uiwebview,Iphone,Ios,Ios4,Uiwebview,是我还是在UIWebView中禁用了标记上的操作表?例如,在Safari中,当您想在本地保存图像时,您可以按住图像以显示操作表。但它在我的自定义UIWebView中不起作用。我的意思是,它仍然适用于标记,也就是说,当我触摸并按住html链接时,会显示一个操作表。但不适用于标记 我尝试过在css中放置img{-webkit touch callout:inherit;},但没有成功。另一方面,当我双击并按住图像时,会显示一个复制气球 所以问题是,标记的默认操作表标注是否已为UIWebView禁用?

是我还是在UIWebView中禁用了
标记上的操作表?例如,在Safari中,当您想在本地保存图像时,您可以按住图像以显示操作表。但它在我的自定义UIWebView中不起作用。我的意思是,它仍然适用于
标记,也就是说,当我触摸并按住html链接时,会显示一个操作表。但不适用于
标记

我尝试过在css中放置
img{-webkit touch callout:inherit;}
,但没有成功。另一方面,当我双击并按住图像时,会显示一个复制气球

所以问题是,
标记的默认操作表标注是否已为UIWebView禁用?那么,有没有办法重新启用它?我在谷歌上搜索了很多关于如何在UIWebView中禁用它的问题,所以只有我没有看到弹出窗口吗


提前谢谢

是的,苹果已经在UIWebView中禁用了此功能(以及其他功能),并将其保留为仅用于Safari

但是,通过扩展本教程,您可以自己重新创建

完成本教程后,您将需要添加一些额外的,以便您可以实际保存图像(本教程没有介绍)。 我在0.3秒后添加了一个名为@“tapAndHoldShortNotification”的额外通知,该通知调用了一个只包含禁用调出代码的方法(为了防止在页面仍在加载时弹出默认菜单和您自己的菜单,进行了一点bug修复)

此外,为了检测图像,您需要扩展JSTools.js,这里是我的一个附加函数

function MyAppGetHTMLElementsAtPoint(x,y) {
    var tags = ",";
    var e = document.elementFromPoint(x,y);
    while (e) {
        if (e.tagName) {
            tags += e.tagName + ',';
        }
        e = e.parentNode;
    }
    return tags;
}

function MyAppGetLinkSRCAtPoint(x,y) {
    var tags = "";
    var e = document.elementFromPoint(x,y);
    while (e) {
        if (e.src) {
            tags += e.src;
            break;
        }
        e = e.parentNode;
    }
    return tags;
}

function MyAppGetLinkHREFAtPoint(x,y) {
    var tags = "";
    var e = document.elementFromPoint(x,y);
    while (e) {
        if (e.href) {
            tags += e.href;
            break;
        }
        e = e.parentNode;
    }
    return tags;
}
现在,您可以检测用户单击图像并实际找到他们正在单击的图像url,但是我们需要更改-(void)openContextualMenuAtPoint:方法以提供额外的选项

这也是我的(我试着模仿Safari的行为):

(注意:selectedLinkURL和selectedImageURL在.h文件中声明,以便在整个类中访问它们,以便保存或打开后者的链接

到目前为止,我们刚刚回顾了教程中的代码更改,但现在我们将进入教程中没有介绍的内容(在实际提到如何保存图像或打开链接之前,它将停止)

为了处理用户的选择,我们现在需要添加actionSheet:clickedbuttonindex:method

-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
    if ([[actionSheet buttonTitleAtIndex:buttonIndex] isEqualToString:@"Open"]){
        [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:selectedLinkURL]]];
    }
    else if ([[actionSheet buttonTitleAtIndex:buttonIndex] isEqualToString:@"Copy"]){
        [[UIPasteboard generalPasteboard] setString:selectedLinkURL];
    }
    else if ([[actionSheet buttonTitleAtIndex:buttonIndex] isEqualToString:@"Copy Image"]){
        [[UIPasteboard generalPasteboard] setString:selectedImageURL];
    }
    else if ([[actionSheet buttonTitleAtIndex:buttonIndex] isEqualToString:@"Save Image"]){
        NSOperationQueue *queue = [NSOperationQueue new];
        NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(saveImageURL:) object:selectedImageURL];
        [queue addOperation:operation];
        [operation release];
    }
}
这会检查用户想要做什么,并处理/大多数操作,只有“保存图像”操作需要另一种方法来处理。 在.h中的接口声明中添加一个MBProgressHUB*progressHud;,并在init方法中设置它(无论您从哪个类处理webview)

而-(void)saveImageURL:(NSString*)url;方法实际上会将其保存到图像库中。 (更好的方法是通过NSURLRequest进行下载,并在MBProgressHUDModeDeterminate中更新进度hud,以确定下载实际需要的时间,但这是一个更复杂的组合实现)

当然,将[progressHud release];添加到dealloc方法中

希望这能向您展示如何向apple遗漏的webView添加一些选项。 当然,您可以添加更多内容,如instapaper的“以后阅读”选项或“在Safari中打开”按钮。 (看看这篇文章的篇幅,我明白了为什么最初的教程遗漏了最后的实现细节)

编辑:(更新更多信息)

有人问我关于我在顶部掩盖的细节,"tapAndHoldShortNotification"的问题,所以这是在澄清它

这是我的UIWindow子类,它添加了第二个通知以取消默认选择菜单(这是因为当我尝试教程时,它显示了两个菜单)

然后,通知的处理方式如下:

// in -viewDidLoad

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stopSelection:) name:@"TapAndHoldShortNotification" object:nil];


- (void)stopSelection:(NSNotification*)notification{
    [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.style.webkitTouchCallout='none';"];
}
这只是一个小小的改变,但它修复了一个恼人的小错误,你可以看到两个菜单(标准菜单和你的菜单)


此外,您还可以通过在通知发出时发送触摸位置,然后从该位置显示UIActionSheet来轻松添加对iPad的支持,尽管这是在iPad之前编写的,因此不包括对该位置的支持。

在这个问题上苦苦挣扎了2或3天之后,位置似乎已经计算出来了“相对”到UIWebView的“左上角”(我正在为iOS 7编程)

因此,为了实现这一点,当您在WebView所在的控制器上获得位置时(我将在下面放一段代码),不要添加“滚动偏移量”

片段-上下文菜单操作:

- (void)contextualMenuAction:(NSNotification*)notification {
// Load javascript
[self loadJavascript];

// Initialize the coordinates
CGPoint pt;
pt.x = [[[notification object] objectForKey:@"x"] floatValue];
pt.y = [[[notification object] objectForKey:@"y"] floatValue];

// Convert point from window to view coordinate system
pt = [self.WebView convertPoint:pt fromView:nil];

// Get PAGE and UIWEBVIEW dimensions
CGSize pageDimensions = [self.WebView documentSize];
CGSize webviewDimensions = self.WebView.frame.size;

/***** If the page is in MOBILE version *****/
if (webviewDimensions.width == pageDimensions.width) {

}

/***** If the page is in DESKTOP version *****/
else {
    // convert point from view to HTML coordinate system
    CGSize viewSize = [self.WebView frame].size;
    // Contiens la portion de la page visible depuis la webview (en fonction du zoom)
    CGSize windowSize = [self.WebView windowSize];

    CGFloat factor = windowSize.width / viewSize.width;
    CGFloat factorHeight = windowSize.height / viewSize.height;
    NSLog(@"factor: %f", factor);
        pt.x = pt.x * factor; // ** logically, we would add the offset **
        pt.y = pt.y * factorHeight; // ** logically, we would add the offset **
}

NSLog(@"x: %f and y: %f", pt.x, pt.y);
NSLog(@"WINDOW: width: %f height: %f", [self.WebView windowSize].width, [self.WebView windowSize].height);
NSLog(@"DOCUMENT: width: %f height: %f", pageDimensions.width, pageDimensions.height);
[self openContextualMenuAt:pt];
}
片段-在OpenContextalMenuat:

- (void)contextualMenuAction:(NSNotification*)notification {
// Load javascript
[self loadJavascript];

// Initialize the coordinates
CGPoint pt;
pt.x = [[[notification object] objectForKey:@"x"] floatValue];
pt.y = [[[notification object] objectForKey:@"y"] floatValue];

// Convert point from window to view coordinate system
pt = [self.WebView convertPoint:pt fromView:nil];

// Get PAGE and UIWEBVIEW dimensions
CGSize pageDimensions = [self.WebView documentSize];
CGSize webviewDimensions = self.WebView.frame.size;

/***** If the page is in MOBILE version *****/
if (webviewDimensions.width == pageDimensions.width) {

}

/***** If the page is in DESKTOP version *****/
else {
    // convert point from view to HTML coordinate system
    CGSize viewSize = [self.WebView frame].size;
    // Contiens la portion de la page visible depuis la webview (en fonction du zoom)
    CGSize windowSize = [self.WebView windowSize];

    CGFloat factor = windowSize.width / viewSize.width;
    CGFloat factorHeight = windowSize.height / viewSize.height;
    NSLog(@"factor: %f", factor);
        pt.x = pt.x * factor; // ** logically, we would add the offset **
        pt.y = pt.y * factorHeight; // ** logically, we would add the offset **
}

NSLog(@"x: %f and y: %f", pt.x, pt.y);
NSLog(@"WINDOW: width: %f height: %f", [self.WebView windowSize].width, [self.WebView windowSize].height);
NSLog(@"DOCUMENT: width: %f height: %f", pageDimensions.width, pageDimensions.height);
[self openContextualMenuAt:pt];
}
要加载正确的JS函数,请执行以下操作:

- (void)openContextualMenuAt:(CGPoint)pt {
    // Load javascript
    [self loadJavascript];

    // get the Tags at the touch location
    NSString *tags = [self.WebView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"getHTMLTagsAtPoint(%li,%li);",(long)pt.x,(long)pt.y]];
    ...
}
代码片段-在JSTools.js中:

- (void)contextualMenuAction:(NSNotification*)notification {
// Load javascript
[self loadJavascript];

// Initialize the coordinates
CGPoint pt;
pt.x = [[[notification object] objectForKey:@"x"] floatValue];
pt.y = [[[notification object] objectForKey:@"y"] floatValue];

// Convert point from window to view coordinate system
pt = [self.WebView convertPoint:pt fromView:nil];

// Get PAGE and UIWEBVIEW dimensions
CGSize pageDimensions = [self.WebView documentSize];
CGSize webviewDimensions = self.WebView.frame.size;

/***** If the page is in MOBILE version *****/
if (webviewDimensions.width == pageDimensions.width) {

}

/***** If the page is in DESKTOP version *****/
else {
    // convert point from view to HTML coordinate system
    CGSize viewSize = [self.WebView frame].size;
    // Contiens la portion de la page visible depuis la webview (en fonction du zoom)
    CGSize windowSize = [self.WebView windowSize];

    CGFloat factor = windowSize.width / viewSize.width;
    CGFloat factorHeight = windowSize.height / viewSize.height;
    NSLog(@"factor: %f", factor);
        pt.x = pt.x * factor; // ** logically, we would add the offset **
        pt.y = pt.y * factorHeight; // ** logically, we would add the offset **
}

NSLog(@"x: %f and y: %f", pt.x, pt.y);
NSLog(@"WINDOW: width: %f height: %f", [self.WebView windowSize].width, [self.WebView windowSize].height);
NSLog(@"DOCUMENT: width: %f height: %f", pageDimensions.width, pageDimensions.height);
[self openContextualMenuAt:pt];
}
这是我用来触摸元素的函数

function getHTMLTagsAtPoint(x,y) {
    var tags = ",";
    var element = document.elementFromPoint(x,y);
    while (element) {
        if (element.tagName) {
            tags += element.tagName + ',';
        }
        element = element.parentNode;
    }
    return tags;
}
代码片段-加载JavaScript

我用这个在webview中注入我的JS代码

-(void)loadJavascript {
    [self.WebView stringByEvaluatingJavaScriptFromString:
    [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"JSTools" ofType:@"js"] encoding:NSUTF8StringEncoding error:nil]];
}
这一部分(我所做的一切都超越了默认的UIActionSheet)是基于 @Freerunning的答案是完整的(我几乎完成了他在我的其他课程中所说的一切,就像我的代码所基于的帖子上所说的),我发布的代码片段只是为了向您更“完整”地展示我的代码


希望这有帮助!首先感谢Freerunnering提供的伟大解决方案

但您可以使用UILongPressGestureRecognitor而不是自定义的LongPress识别器来实现这一点。这使得实现起来更加容易:

在包含webView的Viewcontroller中:

将UIgestureRecognitizerDelegate添加到ViewController

let mainJavascript = "function MyAppGetHTMLElementsAtPoint(x,y) { var tags = \",\"; var e = document.elementFromPoint(x,y); while (e) { if (e.tagName) { tags += e.tagName + ','; } e = e.parentNode; } return tags; } function MyAppGetLinkSRCAtPoint(x,y) { var tags = \"\"; var e = document.elementFromPoint(x,y); while (e) { if (e.src) { tags += e.src; break; } e = e.parentNode; } return tags; }  function MyAppGetLinkHREFAtPoint(x,y) { var tags = \"\"; var e = document.elementFromPoint(x,y); while (e) { if (e.href) { tags += e.href; break; } e = e.parentNode; } return tags; }"

func viewDidLoad() {
  ...
  let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(CustomViewController.longPressRecognizerAction(_:)))
  self.webView.scrollView.addGestureRecognizer(longPressRecognizer)
  longPressRecognizer.delegate = self
  ...
}

func longPressRecognizerAction(sender: UILongPressGestureRecognizer) {
  if sender.state == UIGestureRecognizerState.Began {
    let tapPostion = sender.locationInView(self.webView)
    let tags = self.webView.stringByEvaluatingJavaScriptFromString("MyAppGetHTMLElementsAtPoint(\(tapPostion.x),\(tapPostion.y));")
    let href = self.webView.stringByEvaluatingJavaScriptFromString("MyAppGetLinkHREFAtPoint(\(tapPostion.x),\(tapPostion.y));")
    let src = self.webView.stringByEvaluatingJavaScriptFromString("MyAppGetLinkSRCAtPoint(\(tapPostion.x),\(tapPostion.y));")

    print("tags: \(tags)\nhref: \(href)\nsrc: \(src)")
    // handle the results, for example with an UIDocumentInteractionController
  }
}

// Without this function, the customLongPressRecognizer would be replaced by the original UIWebView LongPressRecognizer 
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
  return true
}

就这样!

tapAndHoldShortNotification在哪里使用?Ridcardo:我在底部更新了帖子,并提供了更多信息。如果我没有向下滚动,效果会很好。但是,在向下滚动网络视图,然后长按时,这不起作用。可能它没有计算正确的触摸点
-(void)loadJavascript {
    [self.WebView stringByEvaluatingJavaScriptFromString:
    [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"JSTools" ofType:@"js"] encoding:NSUTF8StringEncoding error:nil]];
}
let mainJavascript = "function MyAppGetHTMLElementsAtPoint(x,y) { var tags = \",\"; var e = document.elementFromPoint(x,y); while (e) { if (e.tagName) { tags += e.tagName + ','; } e = e.parentNode; } return tags; } function MyAppGetLinkSRCAtPoint(x,y) { var tags = \"\"; var e = document.elementFromPoint(x,y); while (e) { if (e.src) { tags += e.src; break; } e = e.parentNode; } return tags; }  function MyAppGetLinkHREFAtPoint(x,y) { var tags = \"\"; var e = document.elementFromPoint(x,y); while (e) { if (e.href) { tags += e.href; break; } e = e.parentNode; } return tags; }"

func viewDidLoad() {
  ...
  let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(CustomViewController.longPressRecognizerAction(_:)))
  self.webView.scrollView.addGestureRecognizer(longPressRecognizer)
  longPressRecognizer.delegate = self
  ...
}

func longPressRecognizerAction(sender: UILongPressGestureRecognizer) {
  if sender.state == UIGestureRecognizerState.Began {
    let tapPostion = sender.locationInView(self.webView)
    let tags = self.webView.stringByEvaluatingJavaScriptFromString("MyAppGetHTMLElementsAtPoint(\(tapPostion.x),\(tapPostion.y));")
    let href = self.webView.stringByEvaluatingJavaScriptFromString("MyAppGetLinkHREFAtPoint(\(tapPostion.x),\(tapPostion.y));")
    let src = self.webView.stringByEvaluatingJavaScriptFromString("MyAppGetLinkSRCAtPoint(\(tapPostion.x),\(tapPostion.y));")

    print("tags: \(tags)\nhref: \(href)\nsrc: \(src)")
    // handle the results, for example with an UIDocumentInteractionController
  }
}

// Without this function, the customLongPressRecognizer would be replaced by the original UIWebView LongPressRecognizer 
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
  return true
}