iOS UIWebView URL攔截

來源:互聯網
上載者:User

標籤:

http://www.cocoachina.com/ios/20150626/12161.html

 

本文譯者:candeladiao,原文:URL filtering for UIWebView on the iPhone
說明:譯者在做app開發時,因為頁面的javascript檔案比較大導致載入速度很慢,所以想把javascript檔案打包在app裡,當UIWebView需要載入該指令碼時就從app本地讀取,但UIWebView並不支援載入本地資源。最後從下文中找到瞭解決方法,第一次翻譯,難免有誤,大家多多指教。

iCab Mobile(一款iOS平台的網頁瀏覽器)要實現一個攔截管理器來過濾頁面上的廣告及其他東西。它有一個簡單的基於URL過濾規則的列表(通常由使用者維護),當頁麵包含的資源(圖片、js以及css等),檔案的URL存在於規則列表中時,資源就不會被載入。

但看一下UIWebView類的API,會發現我們沒有辦法知道UIWebView正在載入什麼資源,更糟的是,當你希望過濾掉某些資源檔的時候,沒有方法可以強制UIWebView不去載入這些檔案,

攔截器看起來貌似沒有可能實現。

當然還是有解決方案的,否則這篇檔案就沒什麼卵用。

正如上面所說,實現攔截器不能靠UIWebView,因為UIWebView沒有提供任何有用的API。

對UIWebView的所有請求,要找到一個能中斷所有HTTP 要求的切入點,我們需要先瞭解一下Cocoa的URL Loading System,因為UIWebView是使用URL Loading System從web端取資料的。我們需要的切入點NSURLCache類就是URL Loading System的一部分。雖然目前iOS系統不會在磁碟上緩衝任何資料(後面的iOS系統版本或許會有不同),因此在UIWebView開始載入前,NSURLCache管理的快取資料通常為空白,但UIWebView仍然會檢測所請求資源檔是否存在於緩衝。所以我們需要做的只是繼承NSURLCache並重載其方法:

1 - (NSCachedURLResponse*)cachedResponseForRequest:(NSURLRequest*)request

UIWebView請求所有資源時都會調用這個方法。因為我們只需要在這個方法裡判斷請求的URL是否是我們想攔截的。如果是則建立一個沒有內容的假response,否則只需調用super方法即可。

如下是實現細節:

1.繼承NSURLCache:

FilteredWebCache.h:

1234 @interface FilteredWebCache : NSURLCache@end

子類的主要代碼

FilteredWebCache.m:

1234567891011121314151617181920212223 #import "FilteredWebCache.h"#import "FilterManager.h"@implementation FilteredWebCache- (NSCachedURLResponse*)cachedResponseForRequest:(NSURLRequest*)request{    NSURL *url = [request URL];    BOOL blockURL = [[FilterMgr sharedFilterMgr] shouldBlockURL:url];    if (blockURL) {        NSURLResponse *response =              [[NSURLResponse alloc] initWithURL:url                                        MIMEType:@"text/plain"                           expectedContentLength:1                                textEncodingName:nil];        NSCachedURLResponse *cachedResponse =              [[NSCachedURLResponse alloc] initWithResponse:response                             data:[NSData dataWithBytes:" " length:1]];        [super storeCachedResponse:cachedResponse forRequest:request];        [cachedResponse release];        [response release];    }    return [super cachedResponseForRequest:request];}@end

首先判斷URL是否需攔截(判斷通過FilterManager類實現,類實現在此不列出)。如果需要,建立一個無內容的響應對象並把它存在cache中。有人可能會認為只需要返回假的響應對象就夠了,沒必要緩衝它。但這樣會因響應對象被系統釋放而導致app crash。不知道為何為會這樣,可能是iOS的bug(Mac OS X 10.5.x也存在同樣問題,而10.4.x及更早的系統上沒有問題),也可能是URL Loading System內部類之間的依賴所致。所以我們先緩衝響應對象。確保所有響應都是真實存在於緩衝中,這也iOS希望的,最重要的是不會crash.

更新:因為假的響應是以大於0的大小來初始化的,看起來結緩衝它也是必要的。

2.建立新的緩衝:

接下來需要建立一個新的緩衝並告訴iOS系統使用新的緩衝代替預設的,這樣當URL Loading System檢測資源緩衝時才會調用上面的代碼。這要在任意UIWebView開始載入頁面前做,顯然應該放在app啟動的時候:

12345678 NSString *path = ...// the path to the cache fileNSUInteger discCapacity = 10*1024*1024;NSUInteger memoryCapacity = 512*1024;FilteredWebCache *cache =      [[FilteredWebCache alloc] initWithMemoryCapacity: memoryCapacity                             diskCapacity: discCapacity diskPath:path];[NSURLCache setSharedURLCache:cache];[cache release];

這裡需要提供一個緩衝儲存路徑。快取檔案由NSURLCache對象自動產生,我們無需事先建立檔案,但要定義快取檔案所存位置(必須是應用程式“沙箱”內,如“tmp”目錄或是“Document”目錄)

這就是實現UIWebView基於URL進行請求過濾的所有內容,看起來其實並不複雜

註:如果過濾規則在app運行過程中會改變,你需要從緩衝中刪除假的響應。NSURLCache提供了刪除方法,所以這不是問題。如果過濾規則不會改變,則無需關心

iOS UIWebView URL攔截

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.