2010年8月11日星期三

自定义NSURLProtocol


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
发表评论