2009-10-16 9 views
16

Pracuję nad aplikacją na iPhone'a od kilku tygodni, a jedną z wcześniej dodanych funkcji był UIWebView, który ładował kontekstowe strony Wikipedii. Było to dość trywialne do wdrożenia i od jakiegoś czasu działa dobrze.Czy ktoś wykrył, że UIWebView nie działa w przypadku niektórych adresów URL?

Dziś odkryłem, że funkcja niespodziewanie przestała działać. Błąkałam się po obwodzie tego kawałka kodu i początkowo zakładałam, że coś złamałem.

Sprawdziłem wszystkie oczywiste miejsca, moje adresy URL, był UIWebView nadal podłączony w XIB itp. Nie znalazłem żadnych problemów.

Badając dalej, Wsadziłem trochę obsługi błędów w moim UIWebViewDelegatedidFailLoadWithError i okazało byłem coraz -999 błąd:

NSURLErrorCancelled

Returned when an asynchronous load is canceled.

A Web Kit framework delegate will receive this error when it performs a cancel operation on a loading resource. Note that an NSURLConnection or NSURLDownload delegate will not receive this error if the download is canceled.

Tak brzmi to jak robienie nowy wniosek (lub anulowanie) przed oryginał się skończył. Sprawdzam mój kod pod kątem czegoś takiego i pojawia się pusty.

Poszedłem więc do mojej zwykłej spirali paranoi i założyłem, że Wikipedia blokuje żądania oparte na UAgent lub coś takiego i udał się na szaloną próbę podżegania do szczęśliwego miejsca. Próby te nie zakończyły się sukcesem iw końcu zwyciężyło zdrowie psychiczne. Stworzyłem prosty skrypt Pythona naśladować żądanie HTTP robiłem z mojej aplikacji w symulatorze, aby zobaczyć, co Wikipedia wysyłał z powrotem:

string = "GET /wiki/Franklin_D._Roosevelt HTTP/1.1\r\nHost: en.wikipedia.org\r\nUser-Agent: test\r\nReferer: http://en.wikipedia.org/wiki/Franklin_D._Roosevelt\r\nAccept: */*\r\nAccept-Language: en-us\r\n_Accept-Encoding: gzip, deflate\r\nConnection: keep-alive\r\n\r\n" 
import socket 
s = socket.socket() 
s.connect(("en.wikipedia.org",80)) 
s.send(string) 
x = s.recv (1000) 
while (x): 
    print x 
    x = s.recv (1000) 

Więc biegnę tego gościa i odkryć, że Wikipedia jest bardzo uprzejmie na moje dane natychmiast i całkowicie. Więc, co się dzieje?

Luki zaczęły pojawiać się w mojej obecnej, paranoidalnej zbroi "To zawsze moja wina" i postanowiłem sprawdzić, czy inne aplikacje iPhone mogą wyświetlać te adresy URL. Publikuję numer tweet z ironicznie zabawnym (bez trudu) adresem URL i sprawdzam, czy Tweetie może wyświetlić adres URL. Nie może.

Znajomy próbuje go w serwisie Twitterific. Taki sam problem. Działa dobrze w Safari i Wikipedii, ale wygląda na to, że aplikacje na iPhone'a używające standardu bagnetowego UIWebView mają problemy ze stronami Wikipedii.

Wystarczy być całkowicie pewien, nie istnieją żadne inne zmienne, stworzyłem simple test app tylko z UIWebView, który ładuje się http://en.wikipedia.com, to nie z powodu tego samego błędu (dodać, że kod na końcu).

Co wy myślicie? Czy to tylko błąd UIWebView? Jakieś gronki firmy Apple wiedzą, co tu się dzieje?

Czy przegapiłem coś zupełnie oczywistego i znów siedzę w pociągu, aby pracować bez moich spodni?

Czekamy na wiadomość, co myślisz. Pamiętaj, że wczoraj wszystko działało dobrze.

debrief (albo Post Mortem jest bardziej właściwe):

Dzięki Duncan do roztworu i całkiem jasny opis tego, co się tu dzieje.

Wygląda na to, że pierwotnie widział powodu błędu, kiedy nie było wdrożenie didFailLoadWithError metodę delegata w ogóle, było to, że zachowanie domyślne dla tej metody jest widocznie wyczyścić UIWebView iw konsekwencji zabić żądanie . Kiedy dodałem swoją implementację, aby dowiedzieć się, co się dzieje, utknąłem w jakimś kodzie, aby zapisać błąd w widoku i, jak wskazuje Duncan, właśnie to dostałem.

Wydaje się dość przerażającym rozwiązaniem, aby zignorować -999 kodów błędów w oddzwanianiu, ale mam się dobrze z taśmą klejącą.

Próbowałem sporo aplikacji, aby przetestować, czy jest to problem z UIWebView (Tweetie, Twitteriffic itp.) I wszystkie miały problem. Wygląda na to, że może to być dość powszechny niedopatrzenie deweloperów. Może Apple może to posprzątać w następnej wersji.

Inną interesującą kwestią jest to, że kiedy zmieniłem adresy URL, aby używać http://en.m.wikipedia.com zamiast http://en.wikipedia.com, problem zniknął.

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib. 
- (void)viewDidLoad { 
    [super viewDidLoad]; 
    _webView = (UIWebView*)self.view; 
    _webView.delegate = self; 

    // load the url 

    // FAIL 
    //NSURL * newUrl = [[[NSURL alloc] initWithString:@"http://en.wikipedia.com"] autorelease]; 

    // OK 
    NSURL * newUrl = [[[NSURL alloc] initWithString:@"http://www.stackoverflow.com"] autorelease]; 

    NSURLRequest * newUrlRequest = [NSURLRequest requestWithURL:newUrl]; 
    [_webView loadRequest:newUrlRequest];          
} 

// delegate stuff 
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)req navigationType:(UIWebViewNavigationType)navigationType { return YES; } 
- (void)webViewDidStartLoad:(UIWebView *)wv 
    { 
    // starting the load, show the activity indicator in the status bar 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; 
} 

- (void)webViewDidFinishLoad:(UIWebView *)webView 
{ 
    // finished loading, hide the activity indicator in the status bar 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; 
} 

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error 
{ 
    NSURLErrorDomain 
    // load error, hide the activity indicator in the status bar 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; 
    [_webView loadHTMLString:[[[NSString alloc] initWithFormat:@"Failed to load page %@", [error localizedDescription]] autorelease] baseURL:nil]; 
} 
+0

Wygląda na to, że wykonałeś tutaj swoje badania. Jestem przekonany. Myślę, że wyświadczyłbyś nam przysługę, gdybyś złożył radar z Apple. Pamiętaj o dołączeniu aplikacji testowej, gdy ją zarchiwizujesz. –

+0

Dzięki Matt. Wypróbowałem pracę Duncana i rzeczywiście rozwiązało to problem. Czuję, że UIWebView źle się zachowuje, ale jeśli działa ... :) – RedBlueThing

+0

Tweety napisałam o błędach i najnowsza wersja Tweetie2 ma poprawkę :) – RedBlueThing

Odpowiedz

17

Wygląda na to jest odpowiedź tutaj:

How do I fix NSURLErrorDomain error -999 in iPhone 3.0 OS

który z kolei odnosi się do:

http://www.iphonedevsdk.com/forum/iphone-sdk-development/6280-uiwebview-didfailloadwitherror-how-get-errors-code-list.html

Wygląda jak trzeba hack jak to w Webview: didFailLoadWithError: delegowanie:

if ([error code] != NSURLErrorCancelled) { 
    //show error alert, etc. 
} 

W zasadzie to, co się dzieje, to delegat otrzymuje "anulowaną" (-999) awarię, która może pochodzić z javascriptu, a może nawet z błędu UIWebView.

Twój kod nie wyświetla nic, ponieważ używasz tego samego interfejsu UIWebView, aby wyświetlić błąd. Gdybyś po prostu napotkał błąd, zobaczyłbyś awarię, ale wtedy strona ładowałaby się dobrze, dając ci wskazówkę, że niepowodzenie jest fałszywe.

Powiązane problemy