2010-02-10 23 views
15

Tôi muốn thông báo cho người dùng khi nhận được lỗi HTTP 404 404. Làm thế nào tôi có thể phát hiện ra điều đó? Tôi đã cố triển khaiCách phát hiện và xử lý các mã lỗi HTTP trong UIWebView?

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error 

nhưng không được gọi khi tôi nhận được lỗi 404.

Trả lời

7

Bạn có thể nắm bắt được URLRequest đây:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 

và tay theo yêu cầu giao cho các đại biểu và trở về không. Sau đó, trong cuộc gọi trả lời nhận được từ NSURLConnection hủy kết nối và nếu mọi thứ đều ổn (kiểm tra phản hồi) tải urlrequest một lần nữa trong chế độ xem web. Đảm bảo trả lại CÓ trong cuộc gọi ở trên khi tải urlrequest lần nữa.

Không phải rất thanh lịch, nhưng nó có thể hoạt động.

+0

Cảm ơn phản hồi của bạn. Làm thế nào tôi có thể tìm kiếm một chuỗi trong chuỗi html? Tôi bị mắc kẹt ở đó. – EEE

+0

Nếu bạn chụp yêu cầu, bạn có thể bắt đầu 'NSUrlconnection' của riêng mình và thu thập dữ liệu kết nối đã nhận, trong' connectionDidFinishLoading', bạn có thể truy cập vào html. – FelixLam

+0

Trên thực tế tôi đã truy cập vào html, vấn đề đã được tìm kiếm một chuỗi trong html trong mục tiêu-c, nhưng tôi đã giải quyết nó trong C. cảm ơn. – EEE

7

Bạn đang diễn giải sai những gì -didFailLoadWithError cho. Về mặt kỹ thuật, yêu cầu đã thành công. Nó có thể nhấn vào máy chủ và thấy rằng tệp bạn đang yêu cầu không tồn tại (tức là 404). Phương thức -didFailLoadWithError sẽ được gọi nếu máy chủ không tồn tại, ví dụ. Máy chủ của bạn tồn tại. Tệp không. Chế độ xem web sẽ không diễn giải lỗi trong nội dung. Mục đích của -didFailLoadWithError từ UIWebViewDelegate Apple Documents là:

Đã gửi nếu không xem được nội dung .

Từ bài viết Wikipedia trên HTTP 404:

Các thông báo lỗi 404 hoặc Not Found là một HTTP tiêu chuẩn mã phản hồi chỉ ra rằng khách hàng đã có thể giao tiếp với máy chủ nhưng máy chủ không thể tìm thấy số điện thoại yêu cầu là . Lỗi 404 không được là nhầm lẫn với lỗi "không tìm thấy máy chủ" hoặc lỗi tương tự, trong đó kết nối với máy chủ đích không được là .

Trong mọi khả năng bạn sẽ phải phân tích cú pháp văn bản phản hồi cho 404 mà bạn có thể có được với kết hợp NSURLConnection/NSURLRequest thay vì chế độ xem web.

Best Regards,

+0

cảm ơn bạn đã trả lời. Tôi chỉ hiểu sai phương thức didFailLoadError. – EEE

+1

phân tích cú pháp văn bản phản hồi cho mã lỗi là một ý tưởng tồi, văn bản phản hồi có thể là bất cứ điều gì! Xem câu trả lời của tôi cho cách thực sự để nhận mã trạng thái HTTP. –

7

NSURLConnection là lớp học mà bạn đang tìm kiếm, tôi không nghĩ rằng điều này có thể được thực hiện trực tiếp trong một UIWebView.

Bạn có thể sử dụng phương pháp đồng bộ

+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error 

Hoặc những người không đồng bộ. Đây là những khó khăn hơn để thiết lập như bạn phải nối tất cả các bit dữ liệu bạn nhận được vào 1 NSData, nhưng kết quả cuối cùng là như nhau.


Bất kể nếu bạn sử dụng phương pháp đồng bộ hoặc không đồng bộ:

Nếu bạn nhận được một NSError * đối tượng sau đó có một lỗi vệ tinh viễn thông. Như đã lưu ý trong các phản hồi khác, đây không phải là mã trạng thái HTTP mà là vấn đề giao tiếp.

Nếu kết nối thành công, bạn nhận được NSURLResponse và NSData. Quan trọng hơn là NSURLResponse cho các yêu cầu HTTP thực sự là phân lớp NSHTTPURLResponse!

Sau đó, bạn phải kiểm tra phản hồi để xem mã lỗi là gì. Hãy thử điều này (nơi _responseInfo là đối tượng NSURLResponse của bạn):

NSInteger httpStatusCode = (NSHTTPURLResponse*)_responseInfo.statusCode; 

responseInfo nên luôn có một NSHTTPURLResponse cho các yêu cầu HTTP ... nhưng bạn có thể là khôn ngoan để có một khẳng định có chỉ trong trường hợp.

NẾU mã trạng thái là thành công (nghĩa là 200) thì đối tượng NSData của bạn phải chứa dữ liệu phản hồi (bất kỳ điều gì có thể). Nếu mã trạng thái chỉ ra một lỗi thì NSData có thể chứa một mô tả văn bản của lỗi từ máy chủ.

NB. Tôi thực sự không khuyên bạn nên phân tích cú pháp đối tượng NSData cho thông báo lỗi. Đó là những gì HTTP 'statusCode' là dành cho!

8

UIWebView không cung cấp bất kỳ chức năng nào để nhận mã trạng thái HTTP cho các yêu cầu mà nó tải. Một giải pháp khác là ngăn chặn quá trình tải yêu cầu của UIWebView bằng cách sử dụng các phương thức UIWebViewDelegate và sử dụng NSURLConnection để phát hiện cách máy chủ phản hồi yêu cầu đó (như đã đề xuất ở trên). Sau đó, bạn có thể thực hiện một hành động thích hợp phù hợp với tình huống. This article giải thích chi tiết về cách khắc phục sự cố trên dự án demo.

Và bạn không cần tiếp tục tải yêu cầu sau khi nhận được phản hồi. Bạn chỉ có thể hủy kết nối trong kết nối - (void): (NSURLConnection *) didReceiveResponse: (NSURLResponse *) trả lời sau khi tìm hiểu mã trạng thái HTTP. Bằng cách này, bạn ngăn không cho kết nối tải bất kỳ dữ liệu phản hồi không cần thiết nào. Sau đó, bạn có thể tải các yêu cầu trong UIWebView lại hoặc hiển thị một thông báo thích hợp lỗi cho người dùng tùy thuộc vào mã trạng thái HTTP, vv

Here is the article

and here is the demo project on github

2

Trong webViewDidFinishLoad:

if ([[(NSHTTPURLResponse*)[[NSURLCache sharedURLCache] cachedResponseForRequest:webView.request] valueForHTTPHeaderField:@"Status"] intValue] == 404){ 
} 

Bạn có thể xem xét giải pháp này so với các giải pháp phức tạp hơn, mặc dù một số phản hồi có thể không được lưu trong bộ nhớ cache. Lưu ý rằng các url sai thường bị lưu vào bộ nhớ cache bởi một hệ thống có cấu hình mặc định.

16

thực hiện của tôi lấy cảm hứng từ phản ứng Radu Simionescu của:

- (void)webViewDidFinishLoad:(UIWebView *)webView { 
    NSCachedURLResponse *urlResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:webView.request]; 
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*) urlResponse.response; 
    NSInteger statusCode = httpResponse.statusCode; 
    if (statusCode > 399) { 
     NSError *error = [NSError errorWithDomain:@"HTTP Error" code:httpResponse.statusCode userInfo:@{@"response":httpResponse}]; 
     // Forward the error to webView:didFailLoadWithError: or other 
    } 
    else { 
     // No HTTP error 
    } 
} 

Nó quản lý lỗi HTTP client (4xx) và các lỗi HTTP server (5xx).

Lưu ý rằng cachedResponseForRequest trả về nil nếu phản hồi không được lưu trong bộ nhớ cache, trong trường hợp đó statusCode được gán cho 0 và phản hồi được coi là không có lỗi.

+0

Cảm ơn tôi nghĩ câu trả lời của bạn là cách chính xác nhất để làm điều đó. – GeneCode

+0

Tôi đã kéo tóc của tôi ra cho đến khi tôi thử nghiệm điều này trên một thiết bị thực sự, giả lập luôn trả về 404 cho tôi. Nó không phải cho đến khi tôi thử nó trên iPad mà nó thực sự làm việc !! – Plasma

+1

nhưng nhiều lần 'cachedResponseForRequest' trả về' Nil' – Mrug

-1

tôi đã sử dụng dưới mã cho giải pháp của tôi

-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{ 
NSLog(@"error :%@",error); 

NSString *strError = [NSString stringWithFormat:@"%@",error]; 

if ([strError rangeOfString:@"Code=-1005"].location == NSNotFound) { 
    NSLog(@"string does not contain Code=-1005"); 
} else 
    NSLog(@"string contains Code=-1005”); 

}

1

Heres là tôi phiên bản nhanh chóng 3 phản ứng @AxelGuilmin:

func webViewDidFinishLoad(_ webView: UIWebView) { 

     guard let request = webView.request else { return } 

     let cachedUrlResponse = URLCache.shared.cachedResponse(for: request) 
     let httpUrlResponse = cachedUrlResponse?.response as? HTTPURLResponse 
     if let statusCode = httpUrlResponse?.statusCode { 
      if statusCode == 404 { 
       // Handling 404 response 
      } 
     } 
    } 
Các vấn đề liên quan