description
通过UIWebView这个类,可以将web内容嵌入到app中。使用步骤分两步,第一步创建一个UIWebView对象,将它添加到window上,第二步发送一个请求去加载web内容。通过这个类可以在访问网页历史记录中的前一页或后一页,甚至还可以通过编程的方式设置一些网页内容的属性
properties
// UIWebView的代理(不包含UIScrollViewDelegate,如果需要可以通过scrollView属性来设置)
@property (nullable, nonatomic, assign) id <UIWebViewDelegate> delegate;
// UIWebView内部的scrollView,可以通过设置scrollView的delegate来监听UIWebView的滚动
@property (nonatomic, readonly, strong) UIScrollView *scrollView;
// 加载webView的请求,在加载完成后可以拿到
@property (nullable, nonatomic, readonly, strong) NSURLRequest *request;
// 是否可以后退,为YES时才能调用goBack方法
@property (nonatomic, readonly, getter=canGoBack) BOOL canGoBack;
// 是否可以前进,为YES时才能调用goForward方法
@property (nonatomic, readonly, getter=canGoForward) BOOL canGoForward;
// 是否正在加载,加载完成或调用stopLoading方法后为NO
@property (nonatomic, readonly, getter=isLoading) BOOL loading;
// 设置web内容是否适应webView的尺寸
// YES相当于UIViewContentModeScaleToFit,而且此时用户可以通过手势放大缩小web内容
// 为NO时尺寸为web内容的真实尺寸,且不能通过手势放大缩小,默认为NO
@property (nonatomic) BOOL scalesPageToFit;
// 数据检测器类型
// 用于检测web中的特殊内容(电话号码、地址、超链接等),点击被检测的web内容时会出现特定功能选择框
@property (nonatomic) UIDataDetectorTypes dataDetectorTypes
// 是否使用HTML中内联播放器播放视频
// 事实上还需要在HTML中的video标签添加webkit-playsinline属性,否则还是会使用系统的全屏播放器
// iPhone Safari defaults to NO. iPad Safari defaults to YES
@property (nonatomic) BOOL allowsInlineMediaPlayback;
// 设置视频是否自动播放,NO自动播放,YES需要点击才可以播放
// 还需要在HTML的video标签中添加autoplay属性,否则无法自动播放
// iPhone and iPad Safari both default to YES
@property (nonatomic) BOOL mediaPlaybackRequiresUserAction;
// 设置音频播放是否支持air play功能,iPhone and iPad Safari both default to YES
@property (nonatomic) BOOL mediaPlaybackAllowsAirPlay;
// 设置是否将数据加载入内存后渲染界面,iPhone and iPad Safari both default to NO
@property (nonatomic) BOOL suppressesIncrementalRendering;
// 设置是否能够打开键盘在webView上交互,default is YES
@property (nonatomic) BOOL keyboardDisplayRequiresUserAction;
// 设置当网页内容超过UIWebView的尺寸时的布局方式,一般会设置UIWebView的scrollView.pagingEnabled = YES一起使用
@property (nonatomic) UIWebPaginationMode paginationMode;
typedef NS_ENUM(NSInteger, UIWebPaginationMode) {
UIWebPaginationModeUnpaginated, //不使用翻页效果
UIWebPaginationModeLeftToRight, //将网页超出部分分页,从左向右进行翻页
UIWebPaginationModeTopToBottom, //将网页超出部分分页,从上向下进行翻页
UIWebPaginationModeBottomToTop, //将网页超出部分分页,从下向上进行翻页
UIWebPaginationModeRightToLeft //将网页超出部分分页,从右向左进行翻页
};
// 设置每一页的尺寸,如果是上下分页就是每页的高度,如果是左右分页就是每页的宽度
@property (nonatomic) CGFloat pageLength;
// 每页之间的间距
@property (nonatomic) CGFloat gapBetweenPages;
// 总页数
@property (nonatomic, readonly) NSUInteger pageCount;
// 这个属性决定CSS的属性分页是可用还是忽略。默认是UIWebPaginationBreakingModePage
@property (nonatomic) UIWebPaginationBreakingMode paginationBreakingMode;
// 是否支持画中画
@property (nonatomic) BOOL allowsPictureInPictureMediaPlayback NS_AVAILABLE_IOS(9_0);
// 设置是否支持超链接的3DTouch操作(peek和pop)
@property (nonatomic) BOOL allowsLinkPreview NS_AVAILABLE_IOS(9_0);
methods
加载UIWebView内容
- 方法一
// 根据NSURLRequest创建一个异步请求加载UIWebView,可以通过stopLoading停止加载或通过loading属性查看是否正在加载
// 加载本地的HTML文件时一般用loadHTMLString:baseURL:,但是可以用来加载本地的其他文件如PDF等
- (void)loadRequest:(NSURLRequest *)request;
// 加载本地文件(非HTML)
NSString *path = [[NSBundle mainBundle] pathForResource:documentName ofType:nil];
NSURL *url = [NSURL fileURLWithPath:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webView loadRequest:request];
- 方法二
// 加载本地HTML文件,string为HTML的文本内容,baseURL指的是CSS、JS资源路径,如果CSS、JS是本地的,就用[[NSBundle mainbundle] resourceURL]即资源包路径,如果是网络资源写nil即可
- (void)loadHTMLString:(NSString *)string baseURL:(nullable NSURL *)baseURL;
// 加载本地HTML文件
NSData *data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"index.html" ofType:nil]];
NSString *htmlStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
[webView loadHTMLString:htmlStr baseURL:[[NSBundle mainBundle] resourceURL]];
- 方法三
// 根据NSData加载UIWebView
- (void)loadData:(NSData *)data MIMEType:(NSString *)MIMEType textEncodingName:(NSString *)textEncodingName baseURL:(NSURL *)baseURL;
NSData *data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"index.html" ofType:nil]];
[webView loadData:data MIMEType:@"text/html" textEncodingName:@"utf-8" baseURL:[[NSBundle mainBundle] resourceURL]];
代理方法UIWebViewDelegate
// webView加载任何一个frame前都会调用该方法,如果返回NO,就不处理这个请求(后续的代理不会执行)
// UIWebViewNavigationType定义了用户在页面上行为
typedef NS_ENUM(NSInteger, UIWebViewNavigationType) {
UIWebViewNavigationTypeLinkClicked, //用户触击了一个链接
UIWebViewNavigationTypeFormSubmitted, //用户提交了一个表单
UIWebViewNavigationTypeBackForward, //用户触击前进或返回按钮
UIWebViewNavigationTypeReload, //用户触击重新加载的按钮
UIWebViewNavigationTypeFormResubmitted, //用户重复提交表单
UIWebViewNavigationTypeOther //发生其它行为
} __TVOS_PROHIBITED;
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
// webView开始加载之后调用
- (void)webViewDidStartLoad:(UIWebView *)webView;
// webView结束加载之后调用
- (void)webViewDidFinishLoad:(UIWebView *)webView;
// webView加载失败后调用
- (void)webView:(UIWebView *)webView didFailLoadWithError:(nullable NSError *)error;
其他方法
// 刷新网页,重新请求一次
- (void)reload;
// 停止网页加载内容
- (void)stopLoading;
// 后退,执行前先判断下canGoBack
- (void)goBack;
// 前进,执行前先判断下canGoForward
- (void)goForward;
很重要的方法:stringByEvaluatingJavaScriptFromString:
我们可以利用stringByEvaluatingJavaScriptFromString:直接执行某个js方法
function hello() {
alert("Hello World!");
}
[self.webView stringByEvaluatingJavaScriptFromString:@"hello()"];
也可以通过这个方法定义function
NSString *helloFunction = @"function hello() { \
alert('Hello World'); \
} \
hello();";
[self.webView stringByEvaluatingJavaScriptFromString:helloFunction];
- 如果上面的方法是在webViewDidFinishLoad:方法中执行的,会出现一些闪屏现象,原因是渲染过后,内部处理JS代码后,页面会再渲染一次
- stringByEvaluatingJavaScriptFromString:必须在主线程中执行,否则会报错,因为它涉及到UI渲染
important
- 不要在UIScrollView中添加UIWebView或者UITableView,这样可能会造成两个对象触摸事件混乱或被错误的处理
-
使用safari的调试工具可以调试UIWebView中加载的html、CSS、javaScript
safari调试.png - 不能继承UIWebView
参考文献
<a href="http://www.jianshu.com/p/84a6b1ac974a">UIWebView&WKWebView如何实现OC与JS互调</a>
<a href="http://www.jianshu.com/p/b3e7fa514ab7?mType=Group"> UIWebView与WKWebView基本使用</a>
网友评论