iOS开发基础45-UIWebview
在iOS开发中,UIWebView是一个非常重要的组件,它可以加载和显示网页内容。本篇文章将详细介绍UIWebView以及和其相关的常用功能和高级特性。
一、UIWebView简介
什么是UIWebView
UIWebView是iOS系统内置的网页浏览控件,功能类似于系统自带的Safari浏览器。UIWebView不仅可以加载远程网页资源,还可以加载本地各种常见的文件类型,如:
- HTML、HTM
- PDF、DOC、PPT、TXT
- MP4等
以下是加载网络和本地资源的示例:
// 加载网络资源
NSURL *url = [NSURL URLWithString:@"https://www.apple.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webView loadRequest:request];
// 加载本地资源
NSString *htmlString = @"<html><body><h1>Hello, World!</h1></body></html>";
[webView loadHTMLString:htmlString baseURL:nil];
键盘工具条显示中文
在UIWebView内输入时,工具条默认显示为英文。为让工具条显示中文,可以通过设置项目的Info.plist文件中的Localization native development region为中文(zh_CN)。
二、UIWebView的常用属性和方法
常用方法
-
reload重新加载(刷新)[webView reload]; -
stopLoading停止加载[webView stopLoading]; -
goBack回退[webView goBack]; -
goForward前进[webView goForward];
常用属性
-
dataDetectorTypes检测的数据类型webView.dataDetectorTypes = UIDataDetectorTypeAll; -
canGoBack是否能回退if (webView.canGoBack) { [webView goBack]; } -
canGoForward是否能前进if (webView.canGoForward) { [webView goForward]; } -
loading是否正在加载if (webView.loading) { [webView stopLoading]; } -
scalesPageToFit是否伸缩内容以适应屏幕当前尺寸webView.scalesPageToFit = YES;
三、UIWebView的代理
通过设置代理,可以监听UIWebView的加载过程。首先,需要让控制器遵循UIWebViewDelegate协议:
@interface MyViewController () <UIWebViewDelegate>
@end
然后实现相关的代理方法:
代理方法
-
webViewDidStartLoad:开始加载- (void)webViewDidStartLoad:(UIWebView *)webView { NSLog(@"Web view did start load"); } -
webViewDidFinishLoad:加载完成- (void)webViewDidFinishLoad:(UIWebView *)webView { NSLog(@"Web view did finish load"); } -
webView:didFailLoadWithError:加载失败- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { NSLog(@"Web view did fail load with error: %@", error.localizedDescription); } -
webView:shouldStartLoadWithRequest:navigationType:在每次加载请求之前调用,可以通过此方法拦截或修改请求- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSString *urlString = request.URL.absoluteString; if ([urlString hasPrefix:@"customscheme://"]) { // Handle custom scheme return NO; } return YES; }
四、NSInvocation和NSMethodSignature
在iOS开发中,我们常常需要将方法和其对应的参数进行封装,并在稍后阶段进行调用。NSInvocation和NSMethodSignature正是实现这种需求的工具。
NSInvocation的使用
下面是一个通过NSInvocation来调用方法的示例:
- (void)invokeExample {
// 方法签名
NSMethodSignature *signature = [self methodSignatureForSelector:@selector(sendMessageWithNumber:andContent:status:)];
if (!signature) {
NSLog(@"Method not found.");
return;
}
// 创建NSInvocation对象
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = self;
invocation.selector = @selector(sendMessageWithNumber:andContent:status:);
// 设置参数
NSString *number = @"10086";
NSString *content = @"Hello";
NSString *status = @"Success";
[invocation setArgument:&number atIndex:2];
[invocation setArgument:&content atIndex:3];
[invocation setArgument:&status atIndex:4];
// 调用方法
[invocation invoke];
}
- (void)sendMessageWithNumber:(NSString *)number andContent:(NSString *)content status:(NSString *)status {
NSLog(@"Number: %@, Content: %@, Status: %@", number, content, status);
}
五、NSInvocation封装
通过分类,我们能够更加灵活地使用NSInvocation来调用带有多个参数的方法。
#import "NSObject+PerformSelector.h"
@implementation NSObject (PerformSelector)
- (id)performSelector:(SEL)aSelector withObjects:(NSArray *)objects {
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:aSelector];
if (!signature) {
NSString *reason = [NSString stringWithFormat:@"No method found for selector %@", NSStringFromSelector(aSelector)];
@throw [NSException exceptionWithName:@"Method Invocation Exception" reason:reason userInfo:nil];
}
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
invocation.target = self;
invocation.selector = aSelector;
NSUInteger argumentCount = signature.numberOfArguments - 2;
NSUInteger count = MIN(objects.count, argumentCount);
for (NSUInteger i = 0; i < count; i++) {
id object = objects[i];
[invocation setArgument:&object atIndex:i + 2];
}
[invocation invoke];
if (signature.methodReturnLength > 0) {
id returnValue;
[invocation getReturnValue:&returnValue];
return returnValue;
}
return nil;
}
@end
使用示例:
NSArray *params = @[@"10086", @"Hello"];
[self performSelector:@selector(sendMessageWithNumber:andContent:) withObjects:params];
六、JavaScript交互
在OC中调用JavaScript
通过stringByEvaluatingJavaScriptFromString方法,可以在UIWebView中执行JavaScript代码:
[webView stringByEvaluatingJavaScriptFromString:@"alert('Hello, World!')"];
在JavaScript中调用OC方法
通过拦截UIWebView的请求,可以在JavaScript中调用OC方法。首先,在JavaScript中定义一个跳转:
function callOCFunction() {
window.location.href = "customscheme://call";
}
然后,在UIWebView的代理方法中处理这个请求:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSString *urlString = request.URL.absoluteString;
NSString *scheme = @"customscheme://";
if ([urlString hasPrefix:scheme]) {
NSString *methodName = [urlString substringFromIndex:scheme.length];
SEL sel = NSSelectorFromString(methodName);
if ([self respondsToSelector:sel]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self performSelector:sel];
#pragma clang diagnostic pop
}
return NO;
}
return YES;
}
- (void)call {
NSLog(@"OC method called from JS");
}
处理多个参数
对于带有多个参数的OC方法,可以通过自定义URL实现不同的方法调用:
// JavaScript中定义跳转
function callOCFunctionWithParams() {
window.location.href = "customscheme://sendMessageWithNumber_andContent_?12345&Hello";
}
在OC中解析并调用:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSString *urlString = request.URL.absoluteString;
NSString *scheme = @"customscheme://";
if ([urlString hasPrefix:scheme]) {
NSString *path = [urlString substringFromIndex:scheme.length];
NSArray *components = [path componentsSeparatedByString:@"?"];
NSString *methodName = components.firstObject;
methodName = [methodName stringByReplacingOccurrencesOfString:@"_" withString:@":"];
SEL sel = NSSelectorFromString(methodName);
if ([self respondsToSelector:sel]) {
NSArray *params = [components.lastObject componentsSeparatedByString:@"&"];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self performSelector:sel withObjects:params];
#pragma clang diagnostic pop
}
return NO;
}
return YES;
}
总结
本文介绍了如何使用UIWebView进行网页资源的加载和访问,并涉及了NSInvocation和NSMethodSignature的高级用法。通过这些特性和工具,iOS开发者可以实现更加丰富和灵活的应用交互,提升用户体验。

浙公网安备 33010602011771号