當前位置:首頁 » 文件管理 » iosuiwebview緩存

iosuiwebview緩存

發布時間: 2022-09-07 17:23:05

Ⅰ 如何實現 javascript 「同步」調用 app 代碼

在 App 混合開發中,app 層向 js 層提供介面有兩種方式,一種是同步介面,一種一非同步介面(不清楚什麼是同步的請看這里的討論)。為了保證 web 流暢,大部分時候,我們應該使用非同步介面,但是某些情況下,我們可能更需要同步介面。同步介面的好處在於,首先 js 可以通過返回值得到執行結果;其次,在混合式開發中,app 層導出的某些 api 按照語義就應該是同步的,否則會很奇怪——一個可能在 for 循環中使用的,執行非常快的介面,比如讀寫某個配置項,設計成非同步會很奇怪。
那麼如何向 js 層導出同步介面呢?
我們知道,在 Android 框架中,通過 WebView.addJavascriptInterface() 這個函數,可以將 java 介面導出到 js 層,並且這樣導出的介面是同步介面。但是在 iOS 的 Cocoa 框架中,想導出同步介面卻不容易,究其原因,是因為 UIWebView 和 WKWebView 沒有 addJavascriptInterface 這樣的功能。同時,Android 這個功能爆出過安全漏洞,那麼,我們有沒有別的方式實現同步調用呢?我們以 iOS UIWebView 為例提供一種實現,WKWebView 和 Android 也可以參考。
為了找到問題的關鍵,我們看一下 iOS 中實現 js 調用 app 的通行方法:
首先,自定義 UIWebViewDelegate,在函數 shouldStartLoadWithRequest:navigationType: 中攔截請求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

- (BOOL) webView:(UIWebView* _Nonnull)webView
shouldStartLoadWithRequest:(NSURLRequest* _Nonnull)request
navigationType:(UIWebViewNavigationType)navigationType {
if ([request.HTTPMethod compare:@"GET" options:NSCaseInsensitiveSearch] != NSOrderedSame) {
// 不處理非 get 請求
return YES;
}

NSURL* url = request.URL;

if ([url.scheme isEqualToString:@'YourCustomProtocol']) {
return [self onMyRequest:request];
}

return YES;
}

這種做法實質上就是將函數調用命令轉化為 url,通過請求的方式通知 app 層,其中 onMyRequest: 是自定義的 request 響應函數。為了發送請求,js 層要建立一個隱藏的 iframe 元素,每次發送請求時修改 iframe 元素的 src 屬性,app 即可攔截到相應請求。

1
2
3
4
5
6
7
8
9
10
11
12
13

/**
* js 向 native 傳遞消息
* @method js_sendMessageToNativeAsync
* @memberof JSToNativeIOSPolyfill
* @public
* @param str {String} 消息字元串,由 HybridMessage 轉換而來
*/
JSToNativeIOSPolyfill.prototype.js_sendMessageToNativeAsync = function (str) {
if (!this.ifr_) {
this._prepareIfr();
}

this.ifr_.src = 'YourCustomProtocol://__message_send__?msg=' + encodeURIComponent(str); }

當 app 執行完 js 調用的功能,執行結果無法直接返回,為了返回結果,普遍採用回調函數方式——js 層記錄一個 callback,app 通過 UIWebView 的 函數調用這個 callback(類似 jsonp 的機制)。
注意,這樣封裝的介面,天然是非同步介面。因為 js_sendMessageToNativeAsync 這個函數會立即返回,不會等到執行結果發回來。
所以,我們要想辦法把 js 代碼「阻塞」住。
請回憶一下,js 中是用什麼方法能把 UI 線程代碼「阻塞」住,同時又不跑滿 CPU?

1
2
3
4

var async = false;
var url = 'http://.com';
var method = 'GET';<br>var req = new XMLHttpRequest();<br>
req.open(method, url, async);<br>req.send(null);

「同步」ajax(其實沒這個詞,ajax 內涵非同步的意思)可以!在 的響應沒返回之前,這段代碼會一直阻塞。一般來說同步請求是不允許使用的,有導致 UI 卡頓的風險。但是在這里因為我們並不會真的去遠端請求內容,所以不妨一用。
至此實現方式已經比較清楚了,梳理一下思路:
使用同步 XMLHttpRequest 配合特殊構造的 URL 通知 app層。
app 層攔截請求執行功能,將結果作為 Response 返回。
XMLHttpRequest.send() 返回,通過 status 和 responseText 得到結果。
那麼,如何攔截請求呢?大家知道,UIWebViewDelegate 是不會攔截 XMLHttpRequest 請求的,但是 iOS 至少給了我們兩個位置攔截這類請求——NSURLCache 和 NSURLProtocol。
一、NSURLCache 是 iOS 中用來實現自定義緩存的類,當你創建了自定義的 NSURLCache 子類對象,並將其設置為全局緩存管理器,所有的請求都會先到這里檢查有無緩存(如果你沒禁掉緩存的話)。我們可以藉助這個性質攔截到介面調用請求,執行並返回數據。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

- (NSCachedURLResponse*) cachedResponseForRequest:(NSURLRequest *)request {
if ([request.HTTPMethod compare:@"GET" options:NSCaseInsensitiveSearch] != NSOrderedSame) {
// 只對 get 請求做自定義處理
return [super cachedResponseForRequest:request];
}

NSURL* url = request.URL;
NSString* path = url.path;
NSString* query = url.query;

if (path == nil || query == nil) {
return [super cachedResponseForRequest:request];
}

LOGF(@"url = %@, path = %@, query = %@", url, path, query);

if ([path isEqualToString:@"__env_get__"]) {
// 讀環境變數
return [self getEnvValueByURL:url]; //*
} else if ([path isEqualToString:@"__env_set__"]) {
// 寫環境變數
return [self setEnvValueByURL:url];
}

return [super cachedResponseForRequest:request];
}

注意注釋有 * 號的一行,即是執行 app 介面,返回結果。這里的結果是一個 NSCachedResponse 對象,就不贅述了。

Ⅱ ios uiwebview 是非同步載入嗎

不是的,uiwebview是同步載入的。
UIWebView是IOS內置的瀏覽器,可以瀏覽網頁,打開文檔 html/htm pdf docx txt等格式的文件。 safari瀏覽器就是通過UIWebView做的。
伺服器將MIME的標識符等放入傳送的數據中告訴瀏覽器使用那種插件讀取相關文件。
uiwebview載入各種本地文件:
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupUI];

NSString *path = [[NSBundle mainBundle] pathForResource:@"關於.docx" ofType:nil];
NSURL *url = [NSURL fileURLWithPath:path];
NSLog(@"%@", [self mimeType:url]);

//webview載入本地文件,可以使用載入數據的方式
//第一個誒參數是一個NSData, 本地文件對應的數據
//第二個參數是MIMEType
//第三個參數是編碼格式
//相對地址,一般載入本地文件不使用,可以在指定的baseURL中查找相關文件。

//以二進制數據的形式載入沙箱中的文件,
NSData *data = [NSData dataWithContentsOfFile:path];

[self.webView loadData:data MIMEType:@"application/vnd.openxmlformats-officedocument.wordprocessingml.document" textEncodingName:@"UTF-8" baseURL:nil];
}

#pragma mark 載入docx文件
- (void)loadDOCX
{

NSString *path = [[NSBundle mainBundle] pathForResource:@"關於.docx" ofType:nil];
NSURL *url = [NSURL fileURLWithPath:path];
NSLog(@"%@", [self mimeType:url]);

NSData *data = [NSData dataWithContentsOfFile:path];

[self.webView loadData:data MIMEType:@"application/vnd.openxmlformats-officedocument.wordprocessingml.document" textEncodingName:@"UTF-8" baseURL:nil];}

#pragma mark 載入pdf文件
- (void)loadPDF
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"iOS6Cookbook.pdf" ofType:nil];
NSURL *url = [NSURL fileURLWithPath:path];
NSLog(@"%@", [self mimeType:url]);

NSData *data = [NSData dataWithContentsOfFile:path];

[self.webView loadData:data MIMEType:@"application/pdf" textEncodingName:@"UTF-8" baseURL:nil];
}

#pragma mark 載入本地文本文件
- (void)loadText
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"關於.txt" ofType:nil];
NSURL *url = [NSURL fileURLWithPath:path];
NSLog(@"%@", [self mimeType:url]);

NSData *data = [NSData dataWithContentsOfFile:path];

[self.webView loadData:data MIMEType:@"text/plain" textEncodingName:@"UTF-8" baseURL:nil];
}

#pragma mark 載入本地html文件
- (void)loadHTML
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"demo.html" ofType:nil];
NSURL *url = [NSURL fileURLWithPath:path];
NSLog(@"%@", [self mimeType:url]);

NSData *data = [NSData dataWithContentsOfFile:path];

[self.webView loadData:data MIMEType:@"text/html" textEncodingName:@"UTF-8" baseURL:nil];
}

#pragma mark 獲取指定URL的MIMEType類型
- (NSString *)mimeType:(NSURL *)url
{
//1NSURLRequest
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//2NSURLConnection

//3 在NSURLResponse里,伺服器告訴瀏覽器用什麼方式打開文件。

//使用同步方法後去MIMEType
NSURLResponse *response = nil;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
return response.MIMEType;
}

Ⅲ ios wkwebview 是否有緩存

1:獲取webviewscrovllviewcontentsize進行設置

-(void)webViewDidFinishLoad:(UIWebView

*)webView{

CGFloat

webViewHeight=[webView.scrollView

contentSize].height;

CGRect

newFrame
=
webView.frame;

newFrame.size.height

=
webViewHeight;

webView.frame

=
newFrame;

}

2:執行js語句 直接獲取html文檔dom高度

-(void)webViewDidFinishLoad:(UIWebView

*)webView{

CGFloat

webViewHeight=

[[webView

:

@"document.body.offsetHeight"]floatValue];

// CGFloat webViewHeight= [[webView
:
@"document.body.scrollHeight"]floatValue];

CGRect

newFrame
=
webView.frame;

newFrame.size.height

=
webViewHeight;

webView.frame

=
newFrame;

}

3.先UIWebView高度設再使用sizeThatFits返剛合適

-(void)webViewDidFinishLoad:(UIWebView

*)webView{

CGSize

actualSize
=
[webView

sizeThatFits:CGSizeZero];

CGRect

newFrame
=
webView.frame;

newFrame.size.height

=
actualSize.height;

webView.frame

=
newFrame;

}

4.遍歷webview視圖 獲取UIWebDocumentView高度即實際高度
Objective-C

-(void)webViewDidFinishLoad:(UIWebView

*)webView{

CGFloat
webViewHeight
=
0.0f;

if
([webView.subviews

count]

>
0)

{

UIView
*scrollerView
=
webView.subviews[0];

if
([scrollerView.subviews

count]

>
0)

{

UIView
*webDocView
=
scrollerView.subviews.lastObject;

if
([webDocView

isKindOfClass:[NSClassFromString(@"UIWebDocumentView")

class]])

{

webViewHeight
=
webDocView.frame.size.height;//獲取文檔高度

webView.frame=

webDocView.frame;

//更新UIWebView 高度

}

}

}

}

Ⅳ ios uiwebview 緩存文件在哪

順便說下NSURLRequest對象,它有個cachePolicy屬性,只要其值為的話,就不會訪問緩存。可喜的是這種情況貌似只有在緩存里沒取到,或是強制刷新時才可能出現。
實際上NSURLCache本身就有磁碟緩存功能,然而在iOS上,NSCachedURLResponse卻被限制為不能緩存到磁碟(NSURLCacheStorageAllowed被視為)。
不過既然知道了原理,那麼只要自己實現一個NSURLCache的子類,然後改寫cachedResponseForRequest:方法,讓它從硬碟讀取緩存即可。

於是就開工吧。這次的demo邏輯比較復雜,因此我就按步驟來說明了。

先定義視圖和控制器。
它的邏輯是打開應用時就嘗試訪問緩存文件,如果發現存在,則顯示緩存完畢;否則就嘗試下載整個網頁的資源;在下載完成後,也顯示緩存完畢。
不過下載所有資源需要解析HTML,甚至是JavaScript和CSS。為了簡化我就直接用一個不顯示的UIWebView載入這個頁面,讓它自動去發起所有請求。
當然,緩存完了還需要觸發事件來顯示網頁。於是再提供一個按鈕,點擊時顯示緩存的網頁,再次點擊就關閉。
順帶一提,我本來想用Google為例的,可惜它自己實現了HTML 5離線瀏覽,也就體現不出這種方法的意義了,於是只好拿網路來墊背。
Objective-c代碼 收藏代碼
#import <UIKit/UIKit.h>

@interface WebViewController : UIViewController <UIWebViewDelegate> {
UIWebView *web;
UILabel *label;
}

@property (nonatomic, retain) UIWebView *web;
@property (nonatomic, retain) UILabel *label;

- (IBAction)click;

@end

#import "WebViewController.h"
#import "URLCache.h"

@implementation WebViewController

@synthesize web, label;

- (IBAction)click {
if (web) {
[web removeFromSuperview];
self.web = nil;
} else {
CGRect frame = {{0, 0}, {320, 380}};
UIWebView *webview = [[UIWebView alloc] initWithFrame:frame];
webview.scalesPageToFit = YES;
self.web = webview;

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www..com/"]];
[webview loadRequest:request];
[self.view addSubview:webview];
[webview release];
}
}

- (void)addButton {
CGRect frame = {{130, 400}, {60, 30}};
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = frame;
[button addTarget:self action:@selector(click) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:@"我點" forState:UIControlStateNormal];
[self.view addSubview:button];
}

- (void)viewDidLoad {
[super viewDidLoad];

URLCache *sharedCache = [[URLCache alloc] initWithMemoryCapacity:1024 * 1024 diskCapacity:0 diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];

CGRect frame = {{60, 200}, {200, 30}};
UILabel *textLabel = [[UILabel alloc] initWithFrame:frame];
textLabel.textAlignment = UITextAlignmentCenter;
[self.view addSubview:textLabel];
self.label = textLabel;

if (![sharedCache.responsesInfo count]) { // not cached
textLabel.text = @"緩存中…";

CGRect frame = {{0, 0}, {320, 380}};
UIWebView *webview = [[UIWebView alloc] initWithFrame:frame];
webview.delegate = self;
self.web = webview;

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www..com/"]];
[webview loadRequest:request];
[webview release];
} else {
textLabel.text = @"已從硬碟讀取緩存";
[self addButton];
}

[sharedCache release];
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
self.web = nil;
label.text = @"請接通網路再運行本應用";
}

- (void)webViewDidFinishLoad:(UIWebView *)webView {
self.web = nil;
label.text = @"緩存完畢";
[self addButton];

URLCache *sharedCache = (URLCache *)[NSURLCache sharedURLCache];
[sharedCache saveInfo];
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];

if (!web) {
URLCache *sharedCache = (URLCache *)[NSURLCache sharedURLCache];
[sharedCache removeAllCachedResponses];
}
}

- (void)viewDidUnload {
self.web = nil;
self.label = nil;
}

- (void)dealloc {
[super dealloc];
[web release];
[label release];
}

@end

Ⅳ ios webview 用RNCachingURLProtocol緩存,怎麼清理緩存

//清除UIWebView的緩存
[[NSURLCachesharedURLCache] removeAllCachedResponses];
試試

Ⅵ 如何改進iOS App的離線使用體驗

打開過的文章、下載過的音頻、查看過的圖片我們都希望Cache到本地,下次不用再向伺服器請求。

首先,我們為了最快讓用戶看到內容,會在ViewDidLoad載入Cache數據,如:

- (void)viewDidLoad {

[self getArticleList:0 length:SECTION_LENGTH useCacheFirst:YES];
}

然後在viewDidAppear中向伺服器請求最新數據,如

- (void)viewDidAppear:(BOOL)animated {

[super viewDidAppear:animated];

//...

[self getArticleList:0 length:SECTION_LENGTH useCacheFirst:NO]
}

當然這里的getArticleList介面有useCacheFirst參數,我們需要網路請求模塊能夠支持這一點,下面就介紹這些庫和工具。
(藉助一些工具很容易能做到這些,而不用自己造輪子。遵循「凡事都應該最簡單,而不過於簡陋」的原則,這里整理一下,方便項目中使用)。

1.NSMutableURLRequest

Sample(參考麒麟的文章《iOS開發之緩存(一):內存緩存》來使用NSURLCache):

NSString *paramURLAsString= @"http://www..com/";
if ([paramURLAsString length] == 0){
NSLog(@"Nil or empty URL is given");
return;
}
NSURLCache *urlCache = [NSURLCache sharedURLCache];
/* 設置緩存的大小為1M*/
[urlCache setMemoryCapacity:1*1024*1024];
//創建一個nsurl
NSURL *url = [NSURL URLWithString:paramURLAsString];
//創建一個請求
NSMutableURLRequest *request =
[NSMutableURLRequest
requestWithURL:url
cachePolicy:
timeoutInterval:60.0f];
//從請求中獲取緩存輸出
NSCachedURLResponse *response =
[urlCache cachedResponseForRequest:request];
//判斷是否有緩存
if (response != nil){
NSLog(@"如果有緩存輸出,從緩存中獲取數據");
[request setCachePolicy:];
}
self.connection = nil;
/* 創建NSURLConnection*/
NSURLConnection *newConnection =
[[NSURLConnection alloc] initWithRequest:request
delegate:self
startImmediately:YES];
self.connection = newConnection;
[newConnection release];

但是NSMutableURLRequest使用起來不夠簡便,在實際項目中我很少用它,而基本使用ASIHTTPRequest來代替。

2.ASIHTTPRequest

你可以從這里找到它的介紹:http://allseeing-i.com/ASIHTTPRequest/,在5.0/4.0及之前iOS版本,ASIHTTPRequest基本是主力的 HTTP requests library,它本身也是Github中的開源項目,但是從iOS 5.0之後逐漸停止維護了。未來的項目可以使用AFNetworking或者MKNetworkKit代替ASIHTTPRequest。

ASIHTTPRequest的簡介如下:

ASIHTTPRequest is an easy to use wrapper around the CFNetwork API
that makes some of the more tedious aspects of communicating with web
servers easier. It is written in Objective-C and works in both Mac OS X
and iPhone applications.

It is suitable performing basic HTTP requests and interacting with
REST-based services (GET / POST / PUT / DELETE). The included
ASIFormDataRequest subclass makes it easy to submit POST data and files
usingmultipart/form-data.

ASIHTTPRequest庫API設計的簡單易用,並且支持block、queue、gzip等豐富的功能,這是該開源項目如此受歡迎的主要原因。

ASIHTTPRequest庫中提供了ASIWebPageRequest組件用於請求網頁,並且能把網頁中的外部資源一並請求下來,但是我在實際項目中使用後發現有嚴重Bug,所以不建議使用。

ASIHTTPRequest庫的介紹中也提到了它可以支持REST-based service,但是與Restfull API打交道我們往往使用下面介紹的的RestKit。

Sample:

NSMutableString *requestedUrl = [[NSMutableString alloc] initWithString:self.url];

//如果優先使用本地數據
ASICachePolicy policy = _useCacheFirst ?
: ( | );

asiRequest = [ASIHTTPRequest requestWithURL:
[NSURL URLWithString:[requestedUrl :NSUTF8StringEncoding]]];

[asiRequest setDownloadCache:[ASIDownloadCache sharedCache]];
[asiRequest setCachePolicy:policy];
[asiRequest setCacheStoragePolicy:];

// Connection
if (_connectionType == ConnectionTypeAsynchronously) {

[asiRequest setDelegate:self];
[asiRequest startAsynchronous];

// Tell we're receiving.
if (!_canceled && [_delegate respondsToSelector:@selector(downloaderDidStart:)])
[_delegate downloaderDidStart:self];
}
else
{
[asiRequest startSynchronous];

NSError *error = [asiRequest error];

if (!error)
{
[self requestFinished:asiRequest];
}
else
{
[self requestFailed:asiRequest];
}
}

[requestedUrl release];

3.RestKit

官方網站:http://restkit.org/,Github開源項目,與 Restfull API 的 Web服務打交道,這個庫非常便捷,它也提供了很完整的Cache機制。

Sample:

+ (void)setCachePolicy:(BOOL)useCacheFirst
{
RKObjectManager* objectManager = [RKObjectManager sharedManager];

if (useCacheFirst) {
objectManager.client.cachePolicy = RKRequestCachePolicyEnabled; //使用本地Cache,如果沒有Cache請求伺服器
}
else
{
objectManager.client.cachePolicy = |RKRequestCachePolicyTimeout; //離線或者超時時使用本地Cache
}
}

+ (BOOL)getHomeTimeline:(NSInteger)maxId
length:(NSInteger)length
delegate:(id<RKObjectLoaderDelegate>)delegate
useCacheFirst:(BOOL)useCacheFirst
{
if (delegate == nil)
return NO;

[iKnowAPI setCachePolicy:useCacheFirst];

//...
}

Cache請求只是RestKit最基本的功能,RestKit真正強大的地方在於處理與RESTful web services交互時的相關工作非常簡便(https://github.com/RestKit/RestKit/wiki),RestKit還可以Cache data model到Core Data中:

Core Data support. Building on top of the object mapping layer,
RestKit provides integration with Apple's Core Data framework. This
support allows RestKit to persist remotely loaded objects directly back
into a local store, either as a fast local cache or a primary data store
that is periodically synced with the cloud. RestKit can populate Core
Data associations for you, allowing natural property based traversal of
your data model. It also provides a nice API on top of the Core Data
primitives that simplifies configuration and querying use cases through
an implementation of the Active Record access pattern.

但實際上RKRequestCachePolicy已經解決了大部分Cache需求。

4.SDWebImage

SDWebImage是Github開源項目:https://github.com/rs/SDWebImage,它用於方便的請求、Cache網路圖片,並且請求完畢後交由UIImageView顯示。

Asynchronous image downloader with cache support with an UIImageView category.

SDWebImage作為UIImageView的一個Category提供的,所以使用起來非常簡單:

// Here we use the new provided setImageWithURL: method to load the web image
[imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

AFNetworking也提供了類似功能(UIImageView+AFNetworking):

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 100.0f)];
[imageView setImageWithURL:[NSURL URLWithString:@"http://i.imgur.com/r4uwx.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder-avatar"]];

5.UIWebView中的圖片Cache

如果你使用UIWebView來展示內容,在離線情況下如果也想能顯示的話需要實現2點:

Cache Html頁面
Cache 圖片等元素

使用上面介紹的網路組件來Cache Html頁面比較便捷,之後使用webView
loadHTMLString即可載入本地Html頁面,而Cache圖片需要更換NSURLCache公共實例為自定義的
NSURLCache(UIWebView使用的即是+[NSURLCache sharedURLCache]):

//設置使用自定義Cache機制
LocalSubstitutionCache *cache = [[[LocalSubstitutionCache alloc] init] autorelease];
[cache setMemoryCapacity:4 * 1024 * 1024];
[cache setDiskCapacity:10 * 1024 * 1024];
[NSURLCache setSharedURLCache:cache];

自定義NSURLCache:

#import <Foundation/Foundation.h>

@interface LocalSubstitutionCache : NSURLCache
{
NSMutableDictionary *cachedResponses;
}

+ (NSString *)pathForURL:(NSURL*)url;

@end

Ⅶ wkwebview後退會使用緩存嗎

wkwebview後退會使用緩存
WKWebView相對於UIWebView強大了很多,內存的消耗相對少了,所提供的介面也豐富了。
navigationDelegate
[objc] view plain print?
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation { // 類似UIWebView的 -webViewDidStartLoad:
NSLog(@"didStartProvisionalNavigation");
[UIApplication sharedApplication]. = YES;
}

- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
NSLog(@"didCommitNavigation");
}

Ⅷ uiwebView有緩存嗎

1.HTML5 , Manifest
最開始我的想法是使用HTML5中的離線存儲功能,也就是分析Manifest文件來存儲和更新部分資源文件。但是經過實踐發現,UIWebView根本不支持HTML5,他只實現了Webkit中頁面渲染的那一部分。所以要實現緩存必須要另闢蹊徑。

2.NSURLCache
盡管在官方的說明文檔裡面說到NSURLCache和NSCachedURLResponse可以用於緩存,但經我測試好像僅僅只能用於載入本地某些資源文件(這里有一篇博客,原文是英文的,這是翻譯過來的)
,而且還有大小的限制(好像根據iphone的版本不同而不同,最小是25KB吧),比如圖片和JS代碼, 而對於整體的頁面無法進行載入。而且經過測試也沒有感覺載入速度有明顯的提高,我用的緩存策略是(可能是沒有讀取本地的緩存文件?),離線模式下也無法載入(可能是baseURL的關系?)。
這找到一篇博客,一種新的解決思路,經過我測試,可以很好的實現緩存。
另外做一點引申,對於動態獲取數據的頁面,我們不需要緩存的那些請求,只要過濾掉就可以了。
先新建一個文件,把所有不需要緩存的請求的URL寫在一個文件里,就象HTML5的 Cache Manifest那樣。
然後需要使用緩存的時候讀取這個文件,並在重寫的- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request 這個方法內對請求進行判斷,如果是屬於這個文件內的,比如web service的請求就直接返回,其他的就繼續處理。

3.ASIHTTPRequest,ASIDownloadCache 和 ASIWebPageRequest
首先我得說,這確實是個很好的框架,使用起來確實很方便,但是對於緩存這個問題,好像也跟第二點提到的效果差不多,載入速度沒有明顯的提升,離線模式下也無法載入。

Ⅸ ios ios 怎麼獲取uiwebview的指定標簽的img

let path = NSBundle.mainBundle().pathForResource("test", ofType: "html")
let url = NSURL(fileURLWithPath: path!)

do {
let html = try String(contentsOfURL: url, encoding: NSUTF8StringEncoding)
// print(html)

// 獲取所有img src中的src鏈接,並將src更改名稱
// 這里直接採用同步獲取數據,非同步也是一樣的道理,為了方便寫demo,僅以同步載入圖片為例。
// 另外,這不考慮清除緩存的問題。
do {
let regex = try NSRegularExpression(pattern: "<img\\ssrc[^>]*/>", options: .AllowCommentsAndWhitespace)

let result = regex.matchesInString(html, options: .ReportCompletion, range: NSMakeRange(0, html.characters.count))

var content = html as NSString
var sourceSrcs: [String: String] = ["": ""]

for item in result {
let range = item.rangeAtIndex(0)

let imgHtml = content.substringWithRange(range) as NSString
var array = [""]

if imgHtml.rangeOfString("src=\"").location != NSNotFound {
array = imgHtml.componentsSeparatedByString("src=\"")
} else if imgHtml.rangeOfString("src=").location != NSNotFound {
array = imgHtml.componentsSeparatedByString("src=")
}

if array.count >= 2 {
var src = array[1] as NSString
if src.rangeOfString("\"").location != NSNotFound {
src = src.substringToIndex(src.rangeOfString("\"").location)

// 圖片鏈接正確解析出來
print(src)

// 載入圖片
// 這里不處理重復載入的問題,實際開發中,應該要做一下處理。
// 也就是先判斷是否已經載入過,且未清理掉該緩存的圖片。如果
// 已經緩存過,否則才執行下面的語句。
let data = NSData(contentsOfURL: NSURL(string: src as String)!)
let localUrl = self.saveImageData(data!, name: (src as String).md5)

// 記錄下原URL和本地URL
// 如果用非同步載入圖片的方式,先可以提交將每個URL起好名字,由於這里使用的是原URL的md5作為名稱,
// 因此每個URL的名字是固定的。
sourceSrcs[src as String] = localUrl
}
}
}

for (src, localUrl) in sourceSrcs {
if !localUrl.isEmpty {
content = content.(src as String, withString: localUrl, options: NSStringCompareOptions.LiteralSearch, range: NSMakeRange(0, content.length))
}
}

print(content as String)
webView.loadHTMLString(content as String, baseURL: url)
} catch {
print("match error")
}
} catch {
print("load html error")
}

熱點內容
雲存儲免費的攝像頭 發布:2024-10-12 00:15:47 瀏覽:620
DA與腳本 發布:2024-10-12 00:14:22 瀏覽:255
如何看配置支不支持黑蘋果 發布:2024-10-12 00:13:45 瀏覽:588
固件怎麼編譯 發布:2024-10-12 00:05:48 瀏覽:90
隨機編譯軌道教學 發布:2024-10-11 23:52:56 瀏覽:412
為什麼人力資源更改密碼還是登錄不了 發布:2024-10-11 23:52:56 瀏覽:468
直線畫中點演算法 發布:2024-10-11 23:52:55 瀏覽:931
帕拉迪堡壘機密碼如何更改 發布:2024-10-11 23:39:58 瀏覽:208
sqlserver期末試題 發布:2024-10-11 23:39:45 瀏覽:599
小度智能音箱如何解除配置 發布:2024-10-11 23:39:06 瀏覽:515