Я пытаюсь написать приложение, которое использует множество java-скриптов внутри UIWebView. И часть этого java-скрипта загружается динамически (с помощью jquery), когда это необходимо.
Файлы index.html и jquery загружаются должным образом, но не файл code.js. Файл code.js представляет собой запрос, подобный этому (отрывок кода java-скрипта из index.html):
function require(moduleName,filePath) {
var uri = filePath;
jQuery.ajax({
type: "GET",
url: uri,
async: false,
dataType: "script",
success: function(content) {
console.log("Receive content of "+moduleName);
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.log("Error content of "+moduleName);
console.log("Status: " + textStatus);
console.log("Thrown error: " + errorThrown);
console.log("h" + XMLHttpRequest.getAllResponseHeaders());
console.log(XMLHttpRequest.responseText);
}
});
}
function start() {
require("test", "code.js");
}
Функция start () вызывается в событии onload тега body файла index.html. Файл code.js содержит только следующие три строки кода:
alert("Loaded file syncronosly");
// HEllo
alert("second");
Вывод, полученный из этого кода, выглядит следующим образом (у меня есть некоторый дополнительный код js, который перенаправляет вызовы console.log в консоль Xcode, которую я пропустил):
UIWebView console: Error content of test
UIWebView console: Status: error
UIWebView console: Thrown error:
UIWebView console: h
UIWebView console: HTTP Error (0 error).
UIWebView console: alert("Loaded file syncronosly");
// HEllo
alert("second");
Я получаю такое поведение, как только пытаюсь вернуть содержимое code.js в переопределенный класс NSURLCache. В конце концов, идея состоит в том, чтобы иметь приложение, часть которого выполняется в UIWebView без необходимости загружать контент с внешнего веб-сервера.
Это сокращенный код класса кэша (LocalSubstitutionCache):
NSString *pathString = [[request URL] absoluteString];
NSLog(@"request => %@", pathString);
NSString* fileToLoad = nil;
if ([pathString isEqualToString:@"http://example.com/index.html"]) {
fileToLoad = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
}
else if ([pathString hasPrefix:@"http://example.com/code.js"]) {
fileToLoad = [[NSBundle mainBundle] pathForResource:@"code" ofType:@"js"];
}
else if ([pathString isEqualToString:@"http://example.com/jquery-1.6.2.min.js"]) {
fileToLoad = [[NSBundle mainBundle] pathForResource:@"jquery-1.6.2.min" ofType:@"js"];
}
if (!fileToLoad) {
// No local data needed for this request let super handle it:
return [super cachedResponseForRequest:request];
}
NSData *data = [NSData dataWithContentsOfFile:fileToLoad];
NSURLResponse *response =
[[NSURLResponse alloc]
initWithURL:[request URL]
MIMEType:[self mimeTypeForPath:pathString]
expectedContentLength:[data length]
textEncodingName:nil];
cachedResponse =
[[NSCachedURLResponse alloc] initWithResponse:response data:data];
(Код кеша отсюда: http://cocoawithlove.com/2010/09/substituting-local-data-for-remote.html)
Теперь в моем контроллере представления (который содержит веб-представление) я делаю следующее:
- (void)viewDidLoad {
[super viewDidLoad];
// This line loads the content with the cache enabled (and does not work):
[_webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://example.com/index.html"]]];
}
Теперь интересно то, что когда я заменяю код в методе viewDidLoad следующим кодом:
- (void) viewDidLoad {
[super viewDidLoad];
// This two line load the content without the cache:
NSString* fileToLoad = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
[_webview loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:fileToLoad]]];
}
Теперь все работает нормально, и у меня отображаются два предупреждения. Поэтому я подозреваю, что то, что я возвращаю в кеш, не совпадает с тем, что возвращает исходный запрос, когда он перехватывается кешем.
Вот что я уже проверил:
- Не использовать URL-адреса файлов для рабочего случая. Мой оригинальный код получает не кешированный код с веб-сервера. Но для примера проекта я использую URL файла, так как это упрощает проект.
- Тип содержимого возвращен. На обоих случаях текст / javascript
- Набор заголовков спец. Я проверил с помощью прокси-сервера http, какие заголовки установлены в запросе, который не кэшируется. Специальные заголовки не установлены.
Моя самая большая проблема заключается в том, что обратный вызов jquery не возвращает никакой полезной информации об ошибке. Я просто получаю вывод ошибки для аргумента textStatus.
Пример проекта можно скачать здесь: http://dl.dropbox.com/u/5426092/LocalCacheJsInjectTest.zip
Надеюсь, кто-нибудь может помочь мне здесь