2010-02-10 114 views

回答

7

你可以捕捉這裏的URLRequest:

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

及以上的委託手請求並返回無。然後在從NSURLConnection接收到的響應呼叫中取消連接,如果一切正常(檢查響應)再次在webview中加載urlrequest。請確保在再次加載urlrequest時在上述呼叫中返回YES。

不是很優雅,但它可能工作。

+0

感謝您的答覆。如何在html字符串中搜索一個字符串?我被困住了。 – EEE 2010-02-12 07:49:14

+0

如果您捕獲請求,您可以啓動自己的'NSUrlconnection'並收集接收到的連接數據,在'connectionDidFinishLoading'中,您可以訪問html。 – FelixLam 2010-02-12 09:45:13

+0

其實我已經訪問過html,問題是在objective-c的html中搜索字符串,但是我已經用c解決了。謝謝。 – EEE 2010-02-12 12:28:10

7

您錯誤地解釋了-didFailLoadWithError的用途。技術上,請求成功。它能夠擊中服務器並發現你所請求的文件不存在(即404)。例如,如果服務器不存在,則會調用-didFailLoadWithError方法。您的服務器存在。該文件沒有。網絡視圖不會解釋內容中的錯誤。 -didFailLoadWithError從UIWebViewDelegate蘋果文檔的目的是:

如果發送Web視圖加載失敗 內容。

從維基百科文章上HTTP 404

404或Not Found錯誤消息是 指示客戶端是能夠 一個HTTP標準響應代碼 與服務器進行通信,但 服務器找不到要求的 。 404錯誤不應該與 混淆「找不到服務器」或 類似的錯誤,其中到目標服務器的連接 根本不可能是 。

在你必須解析爲404,你可以用一個NSURLConnection的/的NSURLRequest組合,而不是一個Web視圖獲取響應文本的所有可能性。

最好的問候,

+0

感謝您的回覆。我只是誤解了didFailLoadError方法。 – EEE 2010-02-11 20:12:27

+1

解析錯誤代碼的響應文本是一個壞主意,響應文本可能是任何東西!查看我的答案,瞭解獲取HTTP狀態代碼的真正方法。 – 2010-06-07 08:12:39

7

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 ......但你可能是明智的,以防萬一有一個斷言那裏。

IF所述的StatusCode是成功的(即200),那麼你NSData對象應包含的響應(無論其可以是)的數據。如果狀態碼指示錯誤,那麼NSData可能包含來自服務器的錯誤的文本描述。

注意:我真的不建議tyring解析錯誤消息的NSData對象。這就是HTTP'statusCode'的用途!

8

UIWebView中不提供用於獲取HTTP狀態代碼爲它加載請求的任何功能。一種解決方法是使用UIWebViewDelegate方法攔截UIWebView的請求加載過程,並使用NSURLConnection來檢測服務器如何響應該請求(如上所述)。然後你可以採取適合這種情況的適當行動。 This article詳細解釋了演示項目的解決方法。

而且你也不需要繼續收到響應後裝載請求。您只需取消連接 - (無效)連接:(NSURLConnection的*)連接didReceiveResponse:(NSURLResponse *)響應學習HTTP狀態代碼後方法。這樣可以防止連接加載任何不必要的響應數據。然後可以再次加載的UIWebView請求或顯示一個適當的錯誤消息,這取決於HTTP狀態代碼的用戶,等等

Here is the article

and here is the demo project on github

2

在webViewDidFinishLoad:

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

您可能會考慮將此解決方案放在其他更復雜的解決方案上,即使某些響應可能無法緩存。請注意,錯誤的URL通常會被具有默認配置的系統緩存。

16

我實現由拉杜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返回nil如果沒有緩存響應,在這種情況下statusCode被分配爲0,並且該響應被認爲是無誤的。

+0

謝謝我認爲你的答案是最正確的方法。 – GeneCode 2016-11-22 08:49:47

+0

我把我的頭髮拉出來,直到我在真實的設備上進行測試,模擬器總是爲我返回一個404。直到我在iPad上試用它時,它才真正起作用! – Plasma 2017-04-28 11:31:10

+1

但很多次'cachedResponseForRequest'返回'Nil' – Mrug 2017-06-15 07:15:41

-1

我用下面的代碼爲我解決

-(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

繼承人是我的SWIFT 3版@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 
      } 
     } 
    }