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开发者可以实现更加丰富和灵活的应用交互,提升用户体验。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步