HTTPエラー404などを受信したときにユーザーに通知したい。どうすればそれを検出できますか?私はすでに実装しようとしました
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
しかし、404エラーを受け取ったときに呼び出されません。
HTTPエラー404などを受信したときにユーザーに通知したい。どうすればそれを検出できますか?私はすでに実装しようとしました
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
しかし、404エラーを受け取ったときに呼び出されません。
Radu Simionescuの応答に触発された私の実装:
- (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
}
}
HTTPクライアントエラー(4xx)とHTTPサーバーエラー(5xx)を管理します。
応答がキャッシュされていない場合はcachedResponseForRequest
returnsに注意してください。その場合、 0に割り当てられ、応答はエラーなしと見なされます。nil
statusCode
ここでURLRequestをキャプチャできます。
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
リクエストを代理人に渡して、いいえを返します。次に、受信した応答呼び出しでNSURLConnection
接続をキャンセルし、すべてが正常である場合(応答を確認)、Webビューにurlrequestをもう一度ロードします。urlrequestを再度ロードするときは、上記の呼び出しで必ずYESを返します。
あまりエレガントではありませんが、うまくいくかもしれません。
-didFailLoadWithErrorの目的を誤って解釈しています。技術的には、リクエストは成功しました。サーバーにアクセスし、要求しているファイル(つまり、404)が存在しないことを検出できました。たとえば、サーバーが存在しない場合、-didFailLoadWithErrorメソッドが呼び出されます。サーバーが存在します。ファイルはそうではありません。Webビューは、コンテンツのエラーを解釈しません。UIWebViewDelegateAppleDocsの-didFailLoadWithErrorの目的は次のとおりです。
Webビューがコンテンツのロードに失敗した場合に送信されます。
HTTP 404に関するウィキペディアの記事から:
404またはNotFoundエラーメッセージは、クライアントがサーバーと通信できたが、サーバーが要求されたものを見つけることができなかったことを示すHTTP標準応答コードです。404エラーは、宛先サーバーへの接続がまったく確立できなかった「サーバーが見つかりません」または同様のエラーと混同しないでください。
おそらく、WebビューではなくNSURLConnection/NSURLRequestの組み合わせで取得できる404の応答テキストを解析する必要があります。
よろしくお願いします、
NSURLConnectionはあなたが探しているクラスです、私はこれがUIWebViewで直接行うことができるとは思いません。
同期方式が利用できます
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error
または非同期のもの。1 NSDataに取得するデータのすべてのビットを追加する必要があるため、これらのセットアップは困難ですが、最終的な結果は同じです。
同期方式と非同期方式のどちらを使用するかに関係なく、次のようになります。
NSError *オブジェクトを取得した場合は、COMMSエラーが発生しました。他の応答で述べたように、これはHTTPステータスコードではなく、通信の問題です。
接続が成功すると、NSURLResponseとNSDataを取得します。重要なのは、HTTPリクエストのNSURLResponseが実際にはNSHTTPURLResponseサブクラスであるということです。
次に、応答をチェックしてエラーコードを確認する必要があります。これを試してください(_responseInfo
NSURLResponseオブジェクトはどこにありますか):
NSInteger httpStatusCode = (NSHTTPURLResponse*)_responseInfo.statusCode;
responseInfoは常にHTTPリクエストのNSHTTPURLResponseである必要があります...ただし、万が一の場合に備えて、そこにアサートを設定することをお勧めします。
statusCodeが成功(つまり200)の場合、NSDataオブジェクトには応答のデータ(それが何であれ)が含まれている必要があります。ステータスコードがエラーを示している場合、NSDataにはサーバーからのエラーのテキストによる説明が含まれている可能性があります。
NB。エラーメッセージのNSDataオブジェクトを解析するためにタイリングすることは本当にお勧めしません。それがHTTP'statusCode'の目的です!
UIWebViewは、ロードするリクエストのHTTPステータスコードを取得するための機能を提供していません。回避策の1つは、UIWebViewDelegateメソッドを使用してUIWebViewの要求読み込みプロセスをインターセプトし、NSURLConnectionを使用して、サーバーがその要求にどのように応答するかを検出することです(上記のとおり)。その後、状況に適した適切なアクションを実行できます。
また、応答を受信した後、要求のロードを続行する必要はありません。HTTPステータスコードを学習した後、 -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)responseメソッドで接続をキャンセルできます。このようにして、接続が不要な応答データをロードするのを防ぎます。次に、リクエストをUIWebViewに再度ロードするか、HTTPステータスコードなどに応じてユーザーに適切なエラーメッセージを表示できます。
私はiOSとSwiftの開発に不慣れであり、WKWebView(UIではなく)を使用してこれを実現する方法を見つける必要がありました。私は幸運にもこのサイトに出くわし、次の答えを得ることができました。これは私のニーズにぴったりです。それは私がいたのと同じ答えを探している通行人を助けるかもしれません。
この関数の使用(WKNavigationDelegateから):
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void)
次のように、HTTP応答に基づいてカスタム応答を作成できます。
func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
// get the statuscode
guard let statusCode = (navigationResponse.response as? HTTPURLResponse)?.statusCode
else {
decisionHandler(.allow)
return
}
// respond or pass-through however you like
switch statusCode {
case 400..<500:
webView.loadHTMLString("<html><body><h1>You shall not pass!</h1></body></html>", baseURL: nil)
case 500..<600:
webView.loadHTMLString("<html><body><h1>Sorry, our fault.</h1></body></html>", baseURL: nil)
default:
print("all might be well")
}
decisionHandler(.allow)
}
webViewDidFinishLoadの場合:
if ([[(NSHTTPURLResponse*)[[NSURLCache sharedURLCache] cachedResponseForRequest:webView.request] valueForHTTPHeaderField:@"Status"] intValue] == 404){
}
一部の応答がキャッシュされない場合でも、このソリューションを他のより複雑なソリューションよりも検討することができます。間違ったURLは通常、デフォルト構成のシステムによってキャッシュされることに注意してください。
これが@AxelGuilminレスポンスの私の迅速な3バージョンです:
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
}
}
}
ソリューションに以下のコードを使用しました
-(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”);
}