`
lovebirdegg
  • 浏览: 175491 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

7 tips for using UIWebView

阅读更多

For an IPhone app I have been building, I decided to use the UIWebView to render SVG files, instead of doing the vector rendering myself. I needed to have a way to read-in files generated from a vector authoring tool (Illustrator etc.) and after initially looking for an open-source SVG parsing/rendering engine of some sort, I decided on hosting the UIWebView itself instead and use the SVG rendering capability of WebKit. Another option could have been to read in PDF files as PDF is the default meta-file format for Quartz, but I needed programmatic access to each path drawn in the file and it was not apparent to me how I can do that once the PDF is rendered. (Any ideas on that is still welcome of course)

Anyways the point of this post is not really about different options for persisting and reading vector graphic files. I am rather planning to talk a bit about some of the tricky things I found out while trying to use the UIWebView programatically.

Loading the SVG file from your resources folder

This one is quite straightforward. You need to get the correct path for your resources folder and the SVG file in that folder, which can be easily accomplished using the below snippet:

NSString
 *
filePath =
 [
[
NSBundle
 mainBundle]

	pathForResource:
@
"filenameWithoutExtension"
 ofType:
@
"svg"
;
NSData
 *
svgData =
 [
NSData
 dataWithContentsOfFile:
filePath]
;

I also wanted to reference the javascript I used in the SVG file, instead of inline embedding. So I made sure that I set the baseURL correctly for the UIWebView to resolve the path to the javascript file in my resources directory:

NSString
 *
resourcePath =
 [
[
NSBundle
 mainBundle]
 resourcePath]
;
NSURL
 *
baseURL =
 [
[
NSURL
 alloc]
 initFileURLWithPath:
resourcePath isDirectory:
YES
]
;
 
[
self.webView 	loadData:
svgData 
	MIMEType:
@
"image/svg+xml"
	
	textEncodingName:
@
"UTF-8"
 
	baseURL:
baseURL]
;	
[
baseURL release]
;

However to my surprise the above did not work for locating my script file in the SVG referenced as below:

<script type="text/ecmascript" src="foo.js"/>

Well it turns out the src attribute is not actually in the SVG 1.1 specification at all?? The way I solved that problem is to write a build script to embed the script inline to the svg file (i.e. a preprocessing step) and make it part of the build process. (More on that in a later post…)

UIWebView loading contents when it is off-screen

Another surprise was trying to be able to load the SVG file when the UIWebView was off-screen. My design hosted the UIWebView inside a UIScrollView and I was loading the current page and caching the next and previous pages to have a smooth transition as I swipe the scrollview. But it turns out UIWebView has an issue with loading when it is off-screen. I.e. it does not render its contents, when it comes back into screen unless you double tap into it. It sounds more like a bug to me.

To solve this problem, I delayed the actual loading of the SVG file till:

-
 (
void
)
scrollViewDidEndDecelerating:
(
UIScrollView *
)
scrollView

for the current view that is becoming visible and I also made sure that once it is loaded when the UIWebView is visible, I don’t ask it to reload it every time the user swipes the view to left and right.

Calling a javascript function from Objective-C

Part of my application is implemented in Javascript and using the DOM to manipulate the SVG document. I need to be able to call some of my Javascript functions from my Objective-C code. This is fairly straightforward and well documented in the UIWebView reference documentation in the SDK. All you need to do is to create an NSString which contains the Javascript function call, and ask the UIWebView to execute it as shown below:

NSString
 *
jsCommand =
 [
NSString
 stringWithFormat:
@
"setActiveColor(%d, %d, %d);"
, 
	redColor, greenColor, blueColor]
;
[
self.webView stringByEvaluatingJavaScriptFromString:
jsCommand]
;

Javascript communicating back with Objective-C code

What happens when you need to call back your Objective-C code from Javascript? Unfortunately at the time of this writing, there is no proper API for this for the IPhone. (See Apple Documentation for how to do it in MacOS X using WebKit) Fortunately there is a hack, a lot of projects have been using. It basically involves communication through a custom protocol that you make up to pass some parameters and then parsing those parameters in your Objective C code to call your corresponding Objective-C methods.

Basically you create a protocol like below:

myapp:
myfunction:
myparam1:
myparam2

And then in Javascript:

document.location
 =
 "myapp:"
 +
 "myfunction:"
 +
 param1 +
 ":"
 +
 param2;

Then back in your Objective-C code:

-
 (
BOOL
)
webView:
(
UIWebView *
)
webView2 
	shouldStartLoadWithRequest:
(
NSURLRequest
 *
)
request 
	navigationType:
(
UIWebViewNavigationType)
navigationType {

 
	NSString
 *
requestString =
 [
[
request URL]
 absoluteString]
;
	NSArray
 *
components =
 [
requestString componentsSeparatedByString:
@
":"
]
;
 
	if
 (
[
components count]
 > 1
 &&
 
		[
(
NSString
 *
)
[
components objectAtIndex:
0
]
 isEqualToString:
@
"myapp"
]
)
 {

		if
(
[
(
NSString
 *
)
[
components objectAtIndex:
1
]
 isEqualToString:
@
"myfunction"
]
)
 
		{

 
			NSLog(
[
components objectAtIndex:
2
]
)
; // param1

			NSLog(
[
components objectAtIndex:
3
]
)
; // param2

			// Call your method in Objective-C method using the above...

		}

		return
 NO
;
	}

 
	return
 YES
; // Return YES to make sure regular navigation works as expected.

}

Hacky: yes. Gets the job done: yes

Disabling the selection flash

Once you do the above steps, you are basically mostly on your way to have a functioning application that makes use of UIWebView as a component. But as any good IPhone application, you need to add more polish and get rid of the user annoyances.

The first annoyance is, what happens when you tap inside the UIWebView control that is hosting an SVG file. There is a default behavior that happens for all image files, including SVG files. The background of the image (including the border area) flashes quickly to some default grayish color.

Turns out there is a way to turn this off through the use of the WebKit CSS property -webkit-tap-highlight-color, and setting the alpha of the color to 0, in my Javascript code does the trick:

document.documentElement
.style
.webkitTapHighlightColor
 =
 "rgba(0,0,0,0)"
;

Disabling the “action” pop-up

The second thing I needed to disable is the “action” popup that appears if you tap and hold the contents of the UIWebView for a few seconds. This is also controlled through a CSS property called -webkit-touch-callout, and setting that to “none” in this case does the trick:

document.documentElement
.style
.webkitTouchCallout
 =
 "none"
;

Disabling default zoom effect

The final user annoyance I had was the zooming effect that happens by default, when you double tap the content area. Well for many applications this may be a desired effect, but in my case, I needed to disable the zooming. I was hoping that there is another CSS property that is something like webkit-disable-doubletap-zoom but unfortunately no such property exists (at least as of this writing.)

The only other idea I came up with was to be able to detect double tapping and calling the standard preventDefault on the event when that touch happens in my Javascript code. But it turns out that SVG DOM does not at the moment fully implement the touch and gesture events . You should be able to use those when you are hosting regular HTML though.

The final approach I came up with was to be able to intercept the touch events before they even reach UIWebView and stop them in my Objective-C code. To do this, you need to read a bit more about how the touch events are routed in Cocoa . (Requires login to the IPhone Dev Center) Basically the idea is to override the hit testing part of the UIWebView and detect the double tap there. In order to that I subclassed UIWebView and overrode the hitTest method in my implementation. Other than that I keep it up the superclass to do the rest.

-
(
UIView *
)
hitTest:
(
CGPoint)
point withEvent:
(
UIEvent *
)
event {
	
	NSSet
 *
touches =
 [
event allTouches]
;
	BOOL
 forwardToSuper =
 YES
;
	for
 (
UITouch *
touch in
 touches)
 {

		if
 (
[
touch tapCount]
 >=
 2
)
 {

			// prevent this 

			forwardToSuper =
 NO
;
		}
		
	}

	if
 (
forwardToSuper)
{

		//return self.superview;

		return
 [
super hitTest:
point withEvent:
event]
;
	}

	else
 {

		// Return the superview as the hit and prevent

		// UIWebView receiving double or more taps

		return
 self.superview;
	}

}

So this finally did the trick and I was able to prevent the double tap zooming effect as well.

分享到:
评论

相关推荐

    UIWebViewDemo

    **UIWebViewDemo** 是一个基于iOS开发的示例项目,主要展示了如何在应用程序中使用`UIWebView`组件来加载和展示网页内容。`UIWebView`是Apple提供的原生控件,它允许iOS开发者在应用内嵌入网页浏览功能,使得用户...

    UIWebView的使用代码

    之前提到UIWebView使用一个UIScrollView对象来关联web页面的内容,通过UIWebView的scrollView属性即可获得该对象,默认情况下网页长度超出设备视口长度后页面会滚动,用户使用手指滚动页面到页面边距并放开手指后...

    UIWebView使用

    let data = injectionScript.data(using: .utf8)! let html = "&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;" let fullHTML = "\(html)\(injectionScript)" let baseURL = URL(fileURLWithPath: Bundle.main.bundle...

    iPhone开发之UIWebView示例程序

    7. **安全注意事项**:在加载外部网页时,务必注意避免跨站脚本攻击(XSS)和注入问题,确保加载的内容来源可靠。 8. **内存管理**:当不再需要UIWebView时,应正确地释放资源,防止内存泄漏。可以使用`[webView ...

    IOS UIWebView Demo

    7. **安全考虑**:由于UIWebView可能会加载任意网页,所以要注意防止跨站脚本攻击(XSS)和其他安全风险。使用`WKWebView`(iOS 8.0及以后版本)代替UIWebView可以提供更好的安全性。 8. **内存管理**:UIWebView是一...

    UIWebView和js交互

    iOS 7以后,苹果引入了JavaScriptCore框架,它提供了一种在Objective-C或Swift中执行JavaScript代码的方法。通过`WKWebView`(UIWebView的替代品),可以直接操作JavaScriptContext,但UIWebView仍然可以通过`...

    UIWebView+html+css

    在iOS开发中,UIWebView是苹果提供的一种原生控件,用于展示网页内容。这个话题“UIWebView+html+css”主要关注如何在UIWebView中嵌入HTML和CSS,实现可点击的链接以及显示动态的GIF动画效果。下面将详细讲解这个...

    UIWebView的使用

    7. **禁止缩放**:如果你不希望用户缩放网页,可以在web视图的`webViewDidFinishLoad:`代理方法中添加以下代码: ```swift webView.scalesPageToFit = false let noZoom = viewportMetaTag.content = "width=...

    网页视图 UIWebView

    在本文中,我们将深入探讨UIWebView的基本使用,包括网络资源地址字符串的处理以及UIWebView的属性和协议的综合应用。 首先,让我们了解一下**UIWebView的基本使用**。创建一个UIWebView实例很简单,只需要在代码中...

    UIWebView和js交互demo1

    在iOS开发中,UIWebView是苹果提供的一种原生控件,用于展示网页内容。它可以加载HTML、CSS和JavaScript代码,并且具有与Objective-C(OC)代码进行交互的能力。本项目"UIWebView和js交互demo1"就是展示了如何利用...

    UIWebView Demo代码

    7. **内存管理** 注意,UIWebView会占用大量内存,因为它会缓存页面内容。在不再使用时,记得调用`removeFromSuperview`来移除并释放资源。 8. **WKWebView替代** 从iOS 8开始,苹果引入了WKWebView,它在性能和...

    UIWebView与 javascript的交互

    在iOS开发中,UIWebView是苹果提供的一种原生控件,用于在应用内展示网页内容。这个"UIWebView与javascript的交互"的标题暗示了我们正在探讨如何在iOS应用中利用UIWebView与嵌入的HTML页面进行双向通信,即通过...

    Cocos2dx中UIWebView替换为WKWebView

    然而,随着Apple对App Store审核政策的调整,使用UIWebView的App将不再被接受,因为Apple已经将其列为弃用API。在2020年,Apple明确表示,自2020年12月起,所有新提交的App和更新都必须移除UIWebView的使用,转而...

    UIWebView原生与H5交互

    在iOS开发中,UIWebView是苹果提供的一种组件,用于在应用程序中展示网页内容。它不仅可以加载HTML页面,还可以执行JavaScript代码,甚至与原生代码进行交互。这种交互性使得开发者可以利用HTML、CSS和JavaScript的...

    UIWebView加载html

    7. **内存管理**: 使用完UIWebView后,记得释放资源,因为未关闭的Web视图可能导致内存泄漏。可以调用`stopLoading`方法停止当前的加载过程,然后从父视图中移除或置为nil以释放内存。 博客中可能还会涉及到一些...

    Unity 打包iOS 删除 UIWebView引用

    介绍 苹果在审核拒约时给出了以下信息: ...for more information. 但是项目内并未使用 UIWebView API,尝试使用 Unity 构建一个空工程上传到 TestFlight 或者 QuickSDK 进行预先检查,发现依然存在 UIWebV

    UIWebView中加载本地图片

    在iOS开发中,UIWebView是苹果提供的一种用于在应用程序中展示网页内容的组件。它可以加载远程HTML内容,也可以处理本地的HTML文件。然而,当我们要在UIWebView中加载本地图片时,就需要对这个过程做一些特别的处理...

    UIWebView实现https双向认证请求

    for identity in identities { SecIdentityCopyCertificate(identity, &certificate) } } ``` 3. 设置URLSessionDelegate:UIWebView是基于WKWebView的前身,所以我们可以使用URLSession来处理网络请求。设置...

    UIWebView与JS交互小例子

    在iOS开发中,UIWebView是苹果提供的一种原生控件,用于展示网页内容。它可以加载HTML、CSS和JavaScript代码,并且支持与Objective-C代码进行交互,实现App与Web页面的深度融合。本示例将深入探讨如何通过UIWebView...

Global site tag (gtag.js) - Google Analytics