webview 自定义重定向与缓存 利器 ~ 很简单,很好用

来源:互联网 发布:查看服务器端口 编辑:程序博客网 时间:2024/04/29 12:30

https://github.com/rnapier/RNCachingURLProtocol

BACKGROUND

RNCachingURLProtocol is a simple shim for the HTTP protocol (that’s not nearly as scary as it sounds). Anytime a URL is downloaded, the response is cached to disk. Anytime a URL is requested, if we’re online then things proceed normally. If we’re offline, then we retrieve the cached version.

The point of RNCachingURLProtocol is mostly to demonstrate how this is done. The current implementation is extremely simple. In particular, it doesn’t worry about cleaning up the cache. The assumption is that you’re caching just a few simple things, like your “Latest News” page (which was the problem I was solving). It caches all HTTP traffic, so without some modifications, it’s not appropriate for an app that has a lot of HTTP connections (see MKNetworkKit for that). But if you need to cache some URLs and not others, that is easy to implement.

You should also look at AFCache for a more powerful caching engine that is currently integrating the ideas of RNCachingURLProtocol.

USAGE

  1. To build, you will need the Reachability code from Apple (included). That requires that you link withSystemConfiguration.framework.

  2. At some point early in the program (usually application:didFinishLaunchingWithOptions:), call the following:

    [NSURLProtocol registerClass:[RNCachingURLProtocol class]];

  3. There is no step 3.

For more details see Drop-in offline caching for UIWebView (and NSURLProtocol).

EXAMPLE

See the CachedWebView project for example usage.



另外,看下其他知识

NSURL类,提供了操作URLs和URL所指向资源的能力。基础框架同样提供了一系列方法实现url加载、cookie存储、response的缓存、凭据的存储和认证。

框架默认提供了对以下四种协议的资源访问:

The URL loading system provides support for accessing resources using the following protocols:

▪  File Transfer Protocol (ftp://)

▪  Hypertext Transfer Protocol (http://)

▪  Secure 128-bit Hypertext Transfer Protocol (https://)

Local file URLs (file:///)

为了扩展对其他协议的支持,我们可以扩展NSURLProtocol类。

以下例子演示如果对自定义的特殊URL进行操作如<img src=”special:///Special%20Example” id=”stringimage”>,定义了一个特殊的协议”special:///“。当使用UIWebView加载还有该定义的html内容时,我们可以在自己的程序中进行处理。

@interface SpecialProtocol : NSURLProtocol {

}

+ (void) registerSpecialProtocol;

@end

@implementation SpecialProtocol

+ (void) registerSpecialProtocol {

static BOOL inited = NO;

if ( ! inited ) {

[NSURLProtocol registerClass:[SpecialProtocol class]];

inited = YES;

}

}

//判断协议是否收到支持

+ (BOOL)canInitWithRequest:(NSURLRequest *)theRequest {

MLOG(@”%@ received %@ with url=’%@’ and scheme=’%@’”,

self, NSStringFromSelector(_cmd),

[[theRequest URL] absoluteString], [[theRequest URL] scheme]);

/* get the scheme from the URL */

NSString *theScheme = [[theRequest URL] scheme];

/* return true if it matches the scheme we’re using for our protocol. */

return ([theScheme caseInsensitiveCompare: [SpecialProtocol specialProtocolScheme]] == NSOrderedSame );

}

- (void)startLoading {

/* calculate the size of the rendered string */

NSSize tsz = [theString sizeWithAttributes:fontAttrs];

/* allocate an NSImage with large dimensions enough to draw the entire string. */

NSImage *myImage = [[[NSImage alloc] initWithSize: tsz] autorelease];

/* draw the string into the NSImage */

[myImage lockFocus];

[theString drawAtPoint:NSMakePoint(0,0) withAttributes:fontAttrs];

[myImage unlockFocus];

/* retrieve the jfif data for the image */

NSData *data = [myImage JFIFData: 0.75];

/* create the response record, set the mime type to jpeg */

NSURLResponse *response =

[[NSURLResponse alloc] initWithURL:[request URL]

MIMEType:@”image/jpeg”

expectedContentLength:-1

textEncodingName:nil];

/* get a reference to the client so we can hand off the data */

id<NSURLProtocolClient> client = [self client];

/* turn off caching for this response data */

[client URLProtocol:self didReceiveResponse:response

cacheStoragePolicy:NSURLCacheStorageNotAllowed];

/* set the data in the response to our jfif data */

[client URLProtocol:self didLoadData:data];

/* notify that we completed loading */

[client URLProtocolDidFinishLoading:self];

/* we can release our copy */

[response release];

/* if an error occured during our load, here is the code we would

execute to send that information back to webKit.  We’re not using it here,

but you will probably want to use this code for proper error handling.  */

if (0) { /* in case of error */

int resultCode;

resultCode = NSURLErrorResourceUnavailable;

[client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain

code:resultCode userInfo:nil]];

}

/* added the extra log statement here so you can see that stopLoading is called

by the underlying machinery before we leave this routine. */

-    MLOG(@”%@ received %@ – end”, self, NSStringFromSelector(_cmd));

- }

==============

自定义NSURLProtocol后,如何使用

1。在程序中注册

[SpecialProtocol registerSpecialProtocol];

2.访问特殊协议的url

如通过webview 加载html,html中含有sepcial://的特殊url

[[theWebView mainFrame] loadHTMLString:mainWebPage baseURL:nil];

另外一种方法:

NSString *theURLString = [NSString stringWithFormat:@"specail://%@/", thePath];

NSURL *theURL = [NSURL URLWithString:theURLString];

[xxx initWithContentsOfURL: theURL];

3. 遇到匹配的协议时,会调用 SpecialProtocol 判断该协议是否支持

4.   在 startLoading 方法中处理对特殊协议的请求

自定义NSURLProtocol 适用范围

定义自己的文件格式 在程序中注册特殊的url,当访问url时特殊处理

代码示例可以参考apple的示例: SpecialPictureProtocol

原创粉丝点击