Подтвердить что ты не робот

Кто-нибудь нашел, что UIWebView терпит неудачу для некоторых URL-адресов?

Я работаю над iPhone App в течение нескольких недель, и одна из ранних функций, которые я добавил, была UIWebView, которая загружала контекстно-зависимые темы на странице Википедии. Это было довольно тривиально для реализации и в течение некоторого времени работало нормально.

Сегодня я обнаружил, что функциональность неожиданно перестала работать. Я возился по периметру этого фрагмента кода и изначально предполагал, что я что-то сломал.

Я проверил все очевидные места, мои URL-адреса, был UIWebView, все еще подключенный в XIB и т.д. Я не нашел никаких проблем.

Следя далее, я запустил некоторую обработку ошибок в своем UIWebViewDelegate didFailLoadWithError и обнаружил, что получаю ошибку -999:

NSURLErrorCancelled

Возвращается, когда асинхронная загрузка отменен.

Делитель рамки Web Kit будет получить эту ошибку, когда она выполняет отменить операцию при загрузке ресурс. Обратите внимание, что NSURLConnection или делегат NSURLDownload не будет получите эту ошибку, если загрузка отменен.

Таким образом, это звучит так, как сделать новый запрос (или отмену) до того, как оригинал был закончен. Я проверяю свой код на что-то вроде этого и выхожу пустым.

Итак, я вошел в свою обычную нисходящую спираль паранойи и предположил, что Википедия блокирует запросы, основанные на Уэгенте, или что-то в этом роде, и пошла на что-то дикое охота на гусей, пытающееся подделать мой путь обратно в счастливое место. Эти попытки не были успешными, и в конечном итоге здравомыслие возобладало. Я создал простой python script, чтобы имитировать HTTP-запрос, который я делал из своего APP в симуляторе, чтобы увидеть, что Википедия отправляла обратно:

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)

Итак, я запускаю этого парня и обнаруживаю, что Википедия очень любезно возвращает мои данные быстро и полностью. Итак, что происходит?

Chicks начали появляться в моих нынешних параноидальных доспехах "Это всегда моя вина", и я решил проверить, могут ли другие приложения iPhone просматривать эти URL-адреса. Я публикую твит с иронически забавным (я просто удивлен) URL-адресом и проверяю, может ли Tweetie просмотреть URL-адрес. Это невозможно.

Друг пробует это в Twitterific. Та же проблема. Хорошо работает в Safari и в приложении Wikipedia, но, похоже, iPhone-приложения, использующие стандартный UIWebView, имеют проблемы со страницами Википедии.

Чтобы быть полностью уверенным, что нет других переменных, я создал простое тестовое приложение с помощью только UIWebView, который загружает http://en.wikipedia.com, он терпит неудачу с той же ошибкой (добавлено, что код в конце).

Так что вы, ребята, думаете? Это просто ошибка UIWebView? Любые Apple gronks там знают, что здесь происходит?

Я пропустил что-то совершенно очевидное, и я снова сижу в поезде, чтобы работать без штанов?

С нетерпением ждем, что вы думаете. Имейте в виду, вчера это работало хорошо.

Подсветка (или, может быть, Post Mortem более подходит):

Спасибо Duncan за решение и довольно четкое описание того, что здесь происходит.

Похоже, причина, по которой я изначально видел ошибку, когда я вообще не выполнял метод делегирования didFailLoadWithError, заключался в том, что поведение по умолчанию для этого метода, по-видимому, должно очистить UIWebView и, следовательно, убить запрос. Когда я добавил свою реализацию, чтобы узнать, что происходит, я застрял в некотором коде, чтобы записать ошибку в представление, и, как указывает Дункан, это то, что меня достало.

Кажется, это довольно ужасное решение, чтобы игнорировать коды ошибок -999 в обратном вызове, но я хорошо разбираюсь в клейкой ленте.

Я попробовал довольно много приложений, чтобы проверить, была ли это проблемой UIWebView (Tweetie, Twitteriffic и т.д.), и все они имели проблему. Похоже, это может быть довольно распространенным надзором для разработчиков. Возможно, Apple может очистить это в следующей версии.

Другим интересным моментом является то, что когда я переключил свои URL-адреса на использование http://en.m.wikipedia.com вместо http://en.wikipedia.com проблема исчезла.

// 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];
}
4b9b3361

Ответ 1

Похоже, здесь есть ответ:

Как исправить ошибку NSURLErrorDomain -999 в ОС iPhone 3.0

который, в свою очередь, относится к:

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

Похоже, вам нужен взлом, подобный этому в webView: didFailLoadWithError: delegate:

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

В сущности, что происходит, делегат получает "отмененный" (-999) сбой, который может возникнуть в javascript или, возможно, даже в ошибке UIWebView.

С вашим кодом веб-просмотр ничего не показывает, потому что вы используете тот же самый UIWebView, чтобы отобразить ошибку. Если бы у вас была только NSLog'd ошибка, вы бы увидели ошибку, но тогда страница загрузилась бы очень хорошо, давая вам намек на то, что ошибка является фиктивной.