UIWebView的應用和其中的JS與OC間傳值

如今有不少的應用已經採用了WebView和html語言結合的開發模式。html5一直很火由於一份代碼能夠在多個平臺上運用啊,效果各不相同都很美觀,也愈來愈有一些公司直接招後臺程序員和html5程序員,作完的產品再安卓也能用iOS也能用,不用再招雙份的工程師了。應用程序一進去就全是UIWebView,裏面發個請求到本身用html5作的頁面,這就是一個應用!固然今天的主要不是說html5,是說html語言中JS代碼和OC代碼之間的傳值。javascript

先舉例一個簡單的用法:

我在模仿網易彩票作到設置頁面的 常見問題板塊時,扒到的素材是一個html網頁格式的css

也就是說只要設置好了這些按鈕點進去都是一個頁面,只是每個按鈕都綁定了一個 html.id的屬性 ,會html語言的都知道 有了id屬性能夠直接跳到頁面的該位置。html

 

如圖點擊進入後 會跳到這個界面,點擊瞭如何充值按鈕,頁面會自動跳到如何充值頂着邊。若是點擊瞭如何購彩,頁面也會自動跳到自動購彩頂着邊。固然了若是倒數第二個倒數第一個估計就跳不上去了,由於下面已經見底了拖上去會彈回來的因此跳不上去了,這點和C#開發的時候是同樣的。html5

此功能的作法:java

// 創建webView
    UIWebView *web = (UIWebView *)self.view;
    
    // 發送請求前須要請求和請求的連接
    NSURL *url = [[NSBundle mainBundle] URLForResource:_html.html withExtension:nil];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];  // $$$$$
    [web loadRequest:request];
    web.delegate = self;

 

首先要有webView啊,我是手碼建立的程序員

上面html是個人模型,html模型裏html是一個連接打開本地的一個web文件。你也能夠本身找好連接作一個plist再作一個模型web

發送請求,接收數據以後,用webView加載數據瀏覽器

而後再給本身的webView設置代理爲本身,而後遵照協議UIWebViewDelegate,就能夠實現代理方法了緩存

- (void)webViewDidFinishLoad:(UIWebView *)webViewapp

這個方法在頁面加載完成後會調用,在這個方法中來作些js的操做。

想作js的操做,通常都是先把你想要的js代碼拼接接出一個字符串,再用這個方法傳入這個字符串完成操做

    // 拼接一個腳本語言中的 自動定位代碼
    NSString *javascript = [NSString stringWithFormat:@"window.location.href = '#%@'",_html.ID];
    
    // 加載完成後執行這個代碼
    [webView stringByEvaluatingJavaScriptFromString:javascript];

 

裏面的html.ID是字符串中的一個id屬性,控制往哪跳的。

這樣核心功能就完成了。

 

下面再說一個高級點的用法

這是我在模仿網易新聞時作到的新聞詳情界面,

如圖點擊其中的這個庫裏上籃這一行,進入的新聞詳情頁面是用html作的,扒到的數據就是這樣了,可是數據只有亂七八糟的一大串字符,須要本身排版的,特別是圖文混排有點麻煩。。這裏今天就不說了,今天主要說下JS和OC間如何傳值,關於圖文混排 過幾天有時間了再詳細寫一篇。(歡迎關注我評論我)

進去以後是一個新聞詳情頁面,裏面是有圖片的,有的圖片很好看我就想保存,可是問題來了,webView裏面的圖片都是<div><img height= src=></img>什麼什麼的不是UI控件按鈕能夠綁定事件,imgView至少也能夠監聽手勢點擊,這個是網頁啊,如何作到點擊圖片下面彈出一個shit問你保不保存?

這就用到JS代碼和OC代碼見的傳值了,

通常大概思路是這邊發請求,那邊把請求攔下來,再扒出請求url裏的字符串,再各類截取獲得有用的數據

核心思路以下,從一半開始截的

 NSString *onload = @"this.onclick = function() {"
                            "  window.location.href = 'sx:src=' +this.src;"
                                    "};";
        [imgHtml appendFormat:@"<img onload=\"%@\" width=\"%f\" height=\"%f\" src=\"%@\">",onload,width,height,detailImgModel.src];
    // 結束標記
    [imgHtml appendString:@"</div>"];
    // 替換標記
        [body replaceOccurrencesOfString:detailImgModel.ref withString:imgHtml options:NSCaseInsensitiveSearch range:NSMakeRange(0, body.length)];
    }
    return body;

 

其中onload就是加載完畢後才用,而後onclick是JS裏的點擊觸發,window.location.href 是跳往哪裏,後面是一個url 裏面的協議頭是sx:src= 後面是本身圖片的src。 SX是我本身的符號。

就至關於我本身亂寫了一個協議頭sx://www.啥 ,有了協議頭這就是一個跳轉網頁的請求 可是要注意的是,我把// 和www啥的省略了 可是前面這個sx:src=不能再省略了,若是再省略就不是協議頭了,蘋果就會本身給你加一個他的協議頭很長很亂 後面接不住了。

而後寫這個方法 ,webView的代理方法

這個方法是在即將發送請求時會被調用,返回值是一個BOOL類型,說白了就是讓你控制什麼請求容許發出去,什麼請求攔下。

NSString *url = request.URL.absoluteString;
    NSRange range = [url rangeOfString:@"sx:src="];
    if (range.location != NSNotFound) {
        NSInteger begin = range.location + range.length;
        NSString *src = [url substringFromIndex:begin];
        [self savePictureToAlbum:src];
        return NO;
    }
    return YES;

 

先取出這個請求的全url再算出sx:src=這個字符串的範圍,若是是別的真正的請求,是取不到值的,就是NSNotFound,這是容許發出去的

若是取到range了 那就是我寫的這個請求,就從這個範圍日後的字符串全截取下來,這就是html代碼裏那個圖片的地址了this.src。

而後有了url連接就能夠保存到相冊了。

保存到相冊那個方法裏,有兩種選擇一種是從新下載保存,一種是從緩存中取,這種比較省流量。

        NSURLCache *cache =[NSURLCache sharedURLCache];
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:src]];
        NSData *imgData = [cache cachedResponseForRequest:request].data;
        UIImage *image = [UIImage imageWithData:imgData];
        UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);

 

應該都能看懂的吧,大意就是經過這個url找到我上次請求中用這個url弄到的響應數據再轉化成圖片保存入相冊。

到此就完成了JS與OC間的傳值

 

固然若是隻有這樣那還遠遠不夠

這裏是只有一個保存圖片的方法,若是之後又有不少須要攔截的方法,打電話或者發短信等各類各樣的方法,都要一一判斷就太麻煩了。

聰明的作法是把 須要調用的方法名 和 要傳的參數 都統統寫在url裏讓我攔

好比sx:call:&10086 

而後我經過字符串的切割就能夠 獲得一個方法名 call:和一個參數10086

就能夠調用- (void)call:(NSString *)phoneNumber  這個方法了。

NSRange range = [url rangeOfString:@"sx:"];
    if (range.location != NSNotFound) {
        NSUInteger loc = range.location + range.length;
        NSString *path = [url substringFromIndex:loc];
        // 得到方法和參數
        NSArray *methodNameAndParam = [path componentsSeparatedByString:@"&"];
        // 方法名
        NSString *methodName = [methodNameAndParam firstObject];
        // 調用方法
        SEL selector = NSSelectorFromString(methodName);
        if ([self respondsToSelector:selector]) { // 判斷方法的目的: 防止由於方法不存在而報錯

 

這一串代碼寫的很清楚了,得到方法名和參數,把字符串轉化成SEL 而後下面就能夠這麼寫了

調用打電話方法 call 傳的值是 10086

若是遇到了有的方法須要傳多個值。那就該這麼寫

 sx:sendMsg:body:&18686652446&loveyou

經過切割能夠獲得方法名是 sendMsg:body:  要傳的參數用&切開 就是這個(componentsSeparatedByString:@"&")獲得兩個參數電話號碼和信息內容

而後就能夠調用這個方法了

這裏我要說一下

若是要傳入3個4個好多個參數,要用到一個第三方框架

//  Copyright (c) 2015年 shangxianDante. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface NSObject (Extension)
- (id)performSelector:(SEL)selector withObjects:(NSArray *)objects;

@end

 

//  Copyright (c) 2015年 shangxianDante. All rights reserved.
//

#import "NSObject+Extension.h"

@implementation NSObject (Extension)
- (id)performSelector:(SEL)selector withObjects:(NSArray *)objects {
    NSMethodSignature *signature = [self methodSignatureForSelector:selector];
    if (signature) {
        NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
        [invocation setTarget:self];
        [invocation setSelector:selector];
        for(int i = 0; i < [objects count]; i++){
            id object = [objects objectAtIndex:i];
            [invocation setArgument:&object atIndex: (i + 2)];
        }
        [invocation invoke];
        if (signature.methodReturnLength) {
            id anObject;
            [invocation getReturnValue:&anObject];
            return anObject;
        } else {
            return nil;
        }
    } else {
        return nil;
    }
}
@end

 

而後就能夠用這個方法啦

 

最後我想再說個簡單的小技巧

就是由於如今html5很火,就是一份代碼在電腦是一個界面在手機又是一個界面,很漂亮。有時候能夠直接搬過來用可是最下面的頁腳(也許是廣告)又不想要,就能夠直接截了,把人家網站搬過來再把人家的頁腳截了,有意思吧

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://v3.bootcss.com/"]];
    self.webView.delegate = self;
    [self.webView loadRequest:request];
}

#pragma mark - ******************** web代理方法
/**
 *  網頁加載完畢後調用
 */
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    NSString *js = @"document.getElementsByTagName('footer')[0].remove();";
    [webView stringByEvaluatingJavaScriptFromString:js];

 

固然首先你確定要用瀏覽器的開發者工具找到頁腳這部分板塊的名字叫footer啊,而後截了。

董鉑然博客全部文章都是原創歡迎評論和關注)

相關文章
相關標籤/搜索