Примечание: Этот метод хорошо работает с UIKit-х UIWebView
и App12it WebView
, но не работает для нового WKWebView
, который, как представляется, игнорирует систему загрузки URL-адресов. См. Комментарии.
Использовать NSURLProtocol
для обработки локального файла, как если бы они были удаленными запросами. Полный пример см. В PandoraBoy под названием ResourceURLProtocol
. Я пройду через немного упрощенную версию этого здесь. Мы будем читать http://.RESOURCE./path/to/file
, как если бы это было <resources>/path/to/file
.
У каждого NSURLProtocol
будет задан вопрос, может ли он обрабатывать каждый запрос, который появляется в системе. Он должен ответить, может ли он в +canInitWithRequest:
. Мы скажем, если хост .RESOURCE.
, тогда мы сможем его обработать. .RESOURCE.
является незаконным DNS-именем, поэтому он не может конфликтовать с каким-либо реальным хостом (но это законное имя хоста для целей URL-адреса).
NSString *ResourceHost = @".RESOURCE.";
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
return ([[[request URL] scheme] isEqualToString:@"http"] &&
[[[request URL] host] isEqualToString:ResourceHost]);
}
Тогда нам нужно несколько методов бухгалтерского учета. Здесь ничего не видно.
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
return request;
}
-(void)stopLoading {
return;
}
Теперь мы добираемся до мяса. startLoading
- это то, где вы собираетесь делать все, что хотите сделать с запросом.
-(void)startLoading {
NSBundle *thisBundle = [NSBundle bundleForClass:[self class]];
NSString *notifierPath = [[thisBundle resourcePath] stringByAppendingPathComponent:[[[self request] URL] path]];
NSError *err;
NSData *data = [NSData dataWithContentsOfFile:notifierPath
options:NSUncachedRead // Assuming you only need to read this once
error:&err];
if(data != nil) {
// Assuming you're only reading HTML.
// If you need other things, you'll need to work out the correct MIME type
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:[[self request] URL]
MIMEType:@"text/html"
expectedContentLength:[data length]
textEncodingName:nil];
// And we just pass it to the caller
[[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
[[self client] URLProtocol:self didLoadData:data];
[[self client] URLProtocolDidFinishLoading:self];
} else {
NSLog(@"BUG:Unable to load resource:%@:%@", notifierPath, [err description]);
[[self client] URLProtocol:self didFailWithError:err];
}
}
Я также найти немного ResourceURL
обертку полезным:
@implementation ResourceURL
+ (ResourceURL*) resourceURLWithPath:(NSString *)path {
return [[[NSURL alloc] initWithScheme:@"http"
host:ResourceHost
path:path] autorelease];
}
@end
Чтобы использовать его, вам просто нужно сначала зарегистрировать свой обработчик протокола:
[NSURLProtocol registerClass:[ResourceURLProtocol class]];
Тогда вы можете создать " URL ресурса "и загрузить его:
ResourceURL *resource = [ResourceURL resourceURLWithPath:...];
[webView loadRequest:[NSURLRequest requestWithURL:resource]];
Для получения дополнительной информации о NSURLProtocol
, а также более сложного примера кэширования см. Drop-in Offline Caching for UIWebView (and NSURLProtocol).
PandoraBoy полон NSURLProtocol
примеров (ищите все классы с Protocol
в своих именах). Вы можете захватывать, отслеживать, перенаправлять или манипулировать практически всем, что происходит через систему загрузки URL таким образом.
Вы пробовали помещать этот код в фоновый режим? Прямо сейчас, похоже, он работает на основном потоке, что, безусловно, замедлит запуск. Общий 'NSFileManager' является потокобезопасным, поэтому вы не должны сталкиваться с какими-либо проблемами. –
Копирование этих файлов находится на критическом пути моего приложения. Мое приложение - это «WKWebView», который нужно загружать как можно быстрее. – Randomblue
Насколько большой пакет, который вы пытаетесь скопировать? – pteofil