1、html ,js ,oc交互
1.1、点击html页面上的button,调用oc的方法
html代码:
<div class="editCaptcha">
<img id="captchaImg" src="" onClick="refreshCaptcha()">
</div>
js代码:
function refreshCaptcha(){
window.location.href = "huihui://refreshCaptchas/";
}
oc代码:
- (void)refreshCaptchas
{
[self getVerifyCode];
}
1.2、通过oc方法,传值给js,从而改变html页面
html代码:
<div class="editCaptcha">
<img id="captchaImg" src="" onClick="refreshCaptcha()">
</div>
js代码:
function setCaptchaImg(url){
document.getElementById('captchaImg').src = url + '&_=' + new Date().getTime();
}
oc代码:
- (void)getVerifyCode
{
NSMutableDictionary* params = [[NSMutableDictionary alloc]init];
[params safeSetObject:_passport forKey:@"passportId"];
[params safeSetObject:@"58" forKey:@"width"];
[params safeSetObject:@"30" forKey:@"height"];
NSString *url =[XGSDKAuthServer getRequestUrl:@"getCaptcha" withParams:params] ;
[self evaluatingscript:[NSString stringWithFormat:@"setCaptchaImg('%@')", url]];
}
1.3、点击html页面上的button,调用oc的方法并传参给oc方法。
html代码:
<div class="editCaptcha">
<input type="number" id="captcha" placeholder="captcha" value="" style="display: inline-block;">
<img id="captchaImg" src="" onClick="refreshCaptcha()">
</div>
<div class="btn">
<input type="button" id="confirmBtn" value="submit" onClick="onConfirmCaptcha()" >
</div>
js代码:
function onConfirmCaptcha(){
var captcha = getValueById('captcha');
window.location.href = "huihui://onConfirm/?captcha=" + captcha;
}
oc代码:
- (void)onConfirm:(NSArray *)param
{
NSAssert(param.count == 1, @"传入的参数不符合预期");
//获取从html页面传过来的参数
NSString *code = [param safeObjectAtIndex:0];
}
1.4、在oc的方法中获取html页面上的输入框中的值
html代码:
<div class="editCaptcha">
<input type="number" id="captcha" placeholder="captcha" value="" style="display: inline-block;">
<img id="captchaImg" src="" onClick="refreshCaptcha()">
</div>
<div class="btn">
<input type="button" id="confirmBtn" value="submit" onClick="onConfirmCaptcha()" >
</div>
js代码:
function onConfirmCaptcha(){
var captcha = getValueById('captcha');
window.location.href = "kingsoft://onConfirm/?captcha=" + captcha;
}
oc代码:
-(void)ocCall{
NSString *code=[self evaluatingscript:@"onConfirmCaptcha()"];
}
- (NSString *)onConfirm:(NSArray *)param
{
NSAssert(param.count == 1, @"传入的参数不符合预期");
//获取从html页面传过来的参数
NSString *code = [param safeObjectAtIndex:0];
return code;
}
2、html ,js ,oc交互实现原理
js代码:
//获取html的触摸事件
function pageLoad(){
document.ontouchend = function(){
window.location.href = "huihui://documentclick/";
};
}
oc代码:
- (void)documentclick{
NSLog(@"documentclick");
}
@interface XGSDKBaseViewController ()<IMYWebViewDelegate, UIGestureRecognizerDelegate, UIScrollViewDelegate>{
IMYWebView *_webview;
}
- (NSString *)evaluatingscript:(NSString *)script
{
return [_webview stringByEvaluatingJavaScriptFromString:script];
}
#pragma mark - UIWebView delegate
//拦截js中window.location.href方法发送的字符串
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
//huihui://onCancel/
NSString *requestString = [[[request URL] absoluteString] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
if ([requestString hasPrefix:@"ios-log:"]) {
NSLog(@"requestString = %@",[request.URL resourceSpecifier]);
return NO;
}
NSURL *url = [request URL];
if ( [url.absoluteString rangeOfString:@"itms-app"].location != NSNotFound || [url.absoluteString rangeOfString:@"itunes.apple.com"].location != NSNotFound ){
[[UIApplication sharedApplication] openURL:url];
return NO;
}
if ([[request.URL scheme] isEqual:@"huihui"]) {
NSMutableString *resourceSpecifier = [[NSMutableString alloc] initWithString:[[request.URL resourceSpecifier] substringFromIndex:2]];
NSArray *arr = [resourceSpecifier componentsSeparatedByString:@"/"];
NSAssert(arr.count > 0, @"URL参数不符合规范");
if(arr.count > 0){
NSString *paramstr = [request.URL query];
NSArray *paramarr = [paramstr componentsSeparatedByString:@"&"];
NSString *split = paramarr.count > 0 ? @":" : @"";
NSString *method = [NSString stringWithFormat:@"%@%@", [arr firstObject], split];
NSMutableArray *param = nil;
for(NSInteger i = 0; i < paramarr.count; i++){
NSString *str = [paramarr safeObjectAtIndex:i];
if(![str isEmptyOrNull]){
if(!param){
param = [[NSMutableArray alloc] init];
}
NSString *value = [[[str componentsSeparatedByString:@"="] lastObject] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
if(!value){
value = @"";
}
[param safeAddObject:value];
}
}
SEL selector = NSSelectorFromString(method);
if([self respondsToSelector:selector]){
[self performSelectorOnMainThread:selector withObject:param waitUntilDone:YES];
}else{
NSAssert(NO, @"传入了不存在的方法名");
}
return NO;
}
}
return YES;
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSLog(@"load html webViewDidFinishLoad");
//执行还原信息
NSString *htmlInfo = [[XGSDKAuthViewManager sharedManager].htmlInputInfoDic valueForKey:NSStringFromClass([self class])];
if(htmlInfo){
NSString *toJsInfo = [NSString stringWithFormat:@"convertInputInfo('%@')",htmlInfo];
[self evaluatingscript:toJsInfo];
}
[self onload];
[self evaluatingscript:@"pageLoad()"];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(nullable NSError *)error
{
//一个页面没有被完全加载之前收到下一个请求,此时迅速会出现此error,error=-999
//此时可能已经加载完成,则忽略此error,继续进行加载。
if([error code] == NSURLErrorCancelled)
{
NSLog(@"上个页面还没加载完");
return;
}
NSLog(@"load html didFailLoadWithError");
[self setWebViewWithLocalHtml:@"error"];
}
3、若要刷新html页面,只需点击一下html页面即可,不需要重新运行。
分析:当工程部署到模拟器的时候,工程的资源文件会被打包到一个bundle中。若修改了项目目录下的html文件,让其在模拟器上显示,需要再次编译。但是可以从代码上修改项目寻找html文件的路径,让其在项目目录下寻找html而不是在bundle中寻找,就可以做到实时更新。
@interface XGSDKBaseViewController ()<IMYWebViewDelegate, UIGestureRecognizerDelegate, UIScrollViewDelegate>{
IMYWebView *_webview;
}
@end
//设置本地html,localHtml(huihui)
- (void)setWebViewWithLocalHtml:(NSString *)localHtml
{
//js跟css 在不同文件,要baseURL
NSURL *baseURL = nil;
NSString* templateStr = nil;
templateStr = [self getTemplateStr:localHtml];
//判断加载位置...
#if (TARGET_IPHONE_SIMULATOR && DEBUG)
baseURL = [NSURL fileURLWithPath:[self getBaseURLInWorkSpace] isDirectory:YES];
NSLog(@"baseURL=%@",baseURL);
#else
baseURL = [NSURL fileURLWithPath:[self getBaseURLInBundle] isDirectory:YES];
#endif // #if TARGET_IPHONE_SIMULATOR
//调用
[_webview loadHTMLString:templateStr baseURL:baseURL];
}
//返回整个html页面的代码
- (NSString *)getTemplateStr:(NSString *)localHtml
{
NSString *templateStr = nil;
#if (TARGET_IPHONE_SIMULATOR && DEBUG)
templateStr = [self getTemplateInWorkSpaceWithHtml:localHtml];
#else
templateStr = [self getTemplateInBundleWithHtml:localHtml];
#endif // #if TARGET_IPHONE_SIMULATOR
return templateStr;
}
- (NSString *)getBaseURLInWorkSpace
{
NSString *srcDir = [NSString stringWithFormat:@"%@/html/",[SamuraiWatcher sharedInstance].sourcePath];
return srcDir;
}
- (NSString *)getBaseURLInBundle
{
NSString *srcDir = [[XGSDKBaseViewController frameworkBundle] bundlePath];
return srcDir;
}
#pragma mark - 正式环境下的路径
- (NSString *)getTemplateInBundleWithHtml:(NSString *)html
{
//先看看有没有对应的patch文件,有的话就拿,没有就拿bundle
NSString *patch = [self getDownloadPath:@"xx.html"];
NSString *scrPath = nil;
BOOL enablePatch = [self checkFileIsExit:patch];
if(enablePatch){
scrPath = patch;
}else{
scrPath = [self localizedPathForResource:html ofType:@".html" bundle:[self frameworkBundle]];
}
return [NSString stringWithContentsOfFile:scrPath encoding:NSUTF8StringEncoding error:nil];
}
#pragma mark - 工程目录下用的路径
- (NSString *)getTemplateInWorkSpaceWithHtml:(NSString *)html
{
//获取在工程目录下的
NSString *patch = [self getDownloadPath:@"xx.html"];
NSString *srcPath;
BOOL enablePatch = [self checkFileIsExit:patch];
if(enablePatch){
srcPath = patch;
} else {
srcPath = [NSString stringWithFormat:@"%@/%@.html",[self getBaseURLInWorkSpace],html];
NSLog(@"srcPath=%@",srcPath);
}
return [NSString stringWithContentsOfFile:srcPath encoding:NSUTF8StringEncoding error:nil];
}
+(NSString *)getDownloadPath:(NSString *)fileName{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *cachesDirectory = [paths objectAtIndex:0];
NSString *dirPath = [NSString stringWithFormat:@"%@/%@",cachesDirectory, huihui];
NSString *filePath = [NSString stringWithFormat:@"%@%@%@",dirPath,@"/",fileName];
return filePath;
}
+(BOOL)checkFileIsExit:(NSString *)filePath{
// 创建文件管理器
NSFileManager *fileMgr = [NSFileManager defaultManager];
BOOL isFileExist = [fileMgr fileExistsAtPath:filePath];
if (isFileExist) {
return YES;
}
return NO;
}
- (NSString *)getBaseURLInWorkSpace
{
NSString *srcDir = [NSString stringWithFormat:@"%@/html/",[SamuraiWatcher sharedInstance].sourcePath];
return srcDir;
}
#pragma mark - bundle
+ (NSBundle *)frameworkBundle {
static NSBundle* frameworkBundle = nil;
static dispatch_once_t predicate;
NSString *bundle = @"huihui.bundle";
dispatch_once(&predicate, ^{
NSString* mainBundlePath = [[NSBundle mainBundle] resourcePath];
NSString* frameworkBundlePath = [mainBundlePath stringByAppendingPathComponent:bundle];
frameworkBundle = [NSBundle bundleWithPath:frameworkBundlePath];
});
return frameworkBundle;
}
- (NSString *)localizedPathForResource:(NSString *)name ofType:(NSString *)extension bundle:(NSBundle *)bundle {
NSBundle *searchBundle = bundle ? bundle : [NSBundle mainBundle];
NSString *path = [searchBundle pathForResource:name ofType:extension inDirectory:nil forLocalization:'en'];
path = path ? path : [searchBundle pathForResource:name ofType:extension];
return path;
}