Sto provando a scrivere un'applicazione che utilizza molto script java all'interno di UIWebView. E parte di questo script java viene caricato dinamicamente (con jquery) quando è necessario.Caricamento dinamico di file javascript in UIWebView con cache locale non funzionante
L'index.html ei file jquery vengono caricati come previsto ma non il file code.js. Il file code.js è richiesta come questo (snipped del codice java script da 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");
}
La funzione start() viene chiamato in caso onload del tag body del index.html. Il file code.js contiene solo le seguenti tre righe di codice:
alert("Loaded file syncronosly");
// HEllo
alert("second");
L'uscita che ricevo da questo codice simile a questo (ho il codice js qualche ulteriore che inoltra la console.log chiamate alla console Xcode che ho omesso):
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");
ottengo questo comportamento non appena cerco di restituire il contenuto del code.js nella classe NSURLCache ignorato. L'idea alla fine è di avere un'applicazione che parte di una parte viene eseguita in una UIWebView senza la necessità di caricare il contenuto da un server web esterno.
Questo è il codice accorciato della classe cache (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];
(Il codice della cache da qui: http://cocoawithlove.com/2010/09/substituting-local-data-for-remote.html)
Ora a mio controller della vista (che contiene una vista web) faccio la seguente:
- (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"]]];
}
Ora la cosa interessante è che quando ho sostituire il codice nel metodo viewDidLoad con il seguente codice:
- (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]]];
}
Ora tutto funziona correttamente e viene visualizzato il mio avviso. Quindi sospetto che quello che sto tornando nella cache non sia lo stesso di quello che la richiesta originale sta tornando quando viene catturata dalla cache.
Ecco quello che ho già controllato per:
- Non usando gli URL di file per il caso di lavoro. Il mio codice originale ottiene il codice non memorizzato nella cache da un server web. Ma per il progetto di esempio sto usando gli URL dei file perché questo semplifica il progetto.
- Tipo di contenuto restituito. È in entrambi i casi testo/javascript
- Set di intestazioni speciali. Ho controllato con un proxy http quali intestazioni vengono impostate sulla richiesta che non è memorizzata nella cache. Non ci sono set di intestazioni speciali.
Il mio problema più grande è che la richiamata dell'errore jquery non restituisce alcuna informazione di errore utile. Ho appena ricevuto un output di errore per l'argomento textStatus.
È possibile scaricare il progetto di esempio da qui: http://dl.dropbox.com/u/5426092/LocalCacheJsInjectTest.zip
La speranza che qualcuno mi può aiutare qui
Il NSHTTPURLResponse initWithURL: statusCode: metodo è disponibile dal 5.0 anche se non appare nella documentazione. Questo è strano, possiamo usarlo? – groumpf
Ho assunto che possiamo usare questo metodo come è stato aggiunto ed è nel normale file di intestazione visibile per questa classe. Ma finora non ho app con questo codice nell'app store, quindi potrebbe essere diffrent. – Chris
Ora ho inviato correttamente la mia app utilizzando il metodo menzionato. Nessun problema con esso. – Chris