2013-01-22 11 views
10

मैं UIWebView का उपयोग त्रुटि राज्य को नियंत्रित करने के एक webLink और UIWebViewDelegate से वेब लोड करने के लिए:UIWebView पर नहीं गए FailLoadWithError जब वेबलिंक नहीं मिला?

[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:webLink]]]; 


- (void)webViewDidStartLoad:(UIWebView *)webView{ 
    NSLog(@"START LOAD"); 

} 

- (void)webViewDidFinishLoad:(UIWebView *)webView{ 
    NSLog(@"FINISH LOAD"); 
} 

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

लेकिन जब webLink नहीं मिला है, यह नहीं didFailLoadWithError करने के लिए जाना है, यह startLoad और didFinishLoad में जाते हैं। स्थिति को कैसे जाना है जब webLink नहीं मिला? कृपया मदद करें!

+0

वैसे, लोड वास्तव में असफल रहा है, या आपको 404 त्रुटि मिल रही है (जो, वेब दृश्य के परिप्रेक्ष्य से, कोई त्रुटि नहीं है)। – Rob

+0

@Rob धन्यवाद। 404 त्रुटि, लेकिन मुझे नहीं पता कि – Jack

उत्तर

20

दुर्भाग्यवश, 404 (या समान कोड) को UIWebView द्वारा त्रुटियों के रूप में नहीं माना जाता है, क्योंकि एक HTML प्रतिक्रिया प्राप्त हुई थी। इससे भी बदतर, UIWebView हमारे लिए प्रतिक्रिया कोड कैप्चर नहीं करता है, इसलिए आपको NSURLConnection के माध्यम से मैन्युअल रूप से ऐसा करना होगा। मेरी कार्यान्वयन में

@interface ViewController() <UIWebViewDelegate, NSURLConnectionDataDelegate> 

@property (nonatomic) BOOL validatedRequest; 
@property (nonatomic, strong) NSURL *originalUrl; 

@end 

@implementation ViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    // since `shouldStartLoadWithRequest` only validates when a user clicks on a link, we'll bypass that 
    // here and go right to the `NSURLConnection`, which will validate the request, and if good, it will 
    // load the web view for us. 

    self.originalUrl = [NSURL URLWithString:@"http://www.stackoverflow.com"]; 
    NSURLRequest *request = [NSURLRequest requestWithURL:self.originalUrl]; 
    [NSURLConnection connectionWithRequest:request delegate:self]; 
} 

#pragma mark - UIWebViewDelegate 

// you will see this called for 404 errors 

- (void)webViewDidFinishLoad:(UIWebView *)webView 
{ 
    self.validatedRequest = NO; // reset this for the next link the user clicks on 
} 

// you will not see this called for 404 errors 

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

// this is where you could, intercept HTML requests and route them through 
// NSURLConnection, to see if the server responds successfully. 

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 
{ 
    // we're only validating links we click on; if we validated that successfully, though, let's just go open it 
    // nb: we're only validating links we click on because some sites initiate additional html requests of 
    // their own, and don't want to get involved in mediating each and every server request; we're only 
    // going to concern ourselves with those links the user clicks on. 

    if (self.validatedRequest || navigationType != UIWebViewNavigationTypeLinkClicked) 
     return YES; 

    // if user clicked on a link and we haven't validated it yet, let's do so 

    self.originalUrl = request.URL; 

    [NSURLConnection connectionWithRequest:request delegate:self]; 

    // and if we're validating, don't bother to have the web view load it yet ... 
    // the `didReceiveResponse` will do that for us once the connection has been validated 

    return NO; 
} 

#pragma mark - NSURLConnectionDataDelegate method 

// This code inspired by http://www.ardalahmet.com/2011/08/18/how-to-detect-and-handle-http-status-codes-in-uiwebviews/ 
// Given that some ISPs do redirects that one might otherwise prefer to see handled as errors, I'm also checking 
// to see if the original URL's host matches the response's URL. This logic may be too restrictive (some valid redirects 
// will be rejected, such as www.adobephotoshop.com which redirects you to www.adobe.com), but does capture the ISP 
// redirect problem I am concerned about. 

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{  
    NSString *originalUrlHostName = self.originalUrl.host; 
    NSString *responseUrlHostName = response.URL.host; 

    NSRange originalInResponse = [responseUrlHostName rangeOfString:originalUrlHostName]; // handle where we went to "apple.com" and got redirected to "www.apple.com" 
    NSRange responseInOriginal = [originalUrlHostName rangeOfString:responseUrlHostName]; // handle where we went to "www.stackoverflow.com" and got redirected to "stackoverflow.com" 

    if (originalInResponse.location == NSNotFound && responseInOriginal.location == NSNotFound) { 
     NSLog(@"%s you were redirected from %@ to %@", __FUNCTION__, self.originalUrl.absoluteString, response.URL.absoluteString); 
    } 

    if ([response isKindOfClass:[NSHTTPURLResponse class]]) { 
     NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode]; 

     if (statusCode < 200 || statusCode >= 300) { 
      NSLog(@"%s request to %@ failed with statusCode=%d", __FUNCTION__, response.URL.absoluteString, statusCode); 
     } else { 
      self.validatedRequest = YES; 

      [self.webView loadRequest:connection.originalRequest]; 
     } 
    } 

    [connection cancel]; 
} 

@end 

ध्यान दें,, मैं सिर्फ स्थिति कोड के लिए जाँच नहीं कर रहा हूँ, लेकिन मैं यह भी रीडायरेक्ट के लिए जाँच कर रहा हूँ (जो आप या नहीं करने के लिए चाहते हो सकता है हो सकता है): यहाँ इससे निपटने के लिए एक ही रास्ता है । मैं ऐसा इसलिए करता हूं क्योंकि कुछ आईएसपी के अवरोध HTTP अनुरोध, और यदि गंतव्य साइट नहीं मिली है, तो आपको अपने स्वयं के खोज वेब पेज पर रीडायरेक्ट करें (जो मुझे लगता है कि यह जानकर थोड़ा डरावना है कि मेरा आईएसपी हर वेब साइट की तलाश कर रहा है)। और यदि आप वाईफाई के माध्यम से कनेक्ट होने वाले आईफ़ोन से निपट रहे हैं, तो आपको इन अनियमितताओं से निपटना होगा।

तो, उदाहरण के लिए, मेरे कोड ऊपर "http://www.applecom/pages" के लिए खोज कर रहा है (जिसमें मैं जानबूझ कर ".com" है, जो DNS लुकअप विफल की अवधि छोड़े गए), लेकिन जिसके लिए मेरी आईएसपी, वेरिज़ोन अनुरोध को रोका और अपने स्वयं के खोज पृष्ठ पर HTTP कनेक्शन द्वारा निर्देशित कर दिये और इस प्रकार, मेरे ऐप रिपोर्ट कर रहा है:

2013-01-21 23: 14: 21.896 webtest [24198: C07] - [ViewController कनेक्शन: didReceiveResponse :] आपको http://www.applecom/pages से http://search.dnsassist.verizon.net/assist.php?url=www.applecom

से रीडायरेक्ट किया गया था 210

आप इस बारे में सोचना चाहते हैं कि किस प्रकार के रीडायरेक्ट स्वीकार्य हैं (उदाहरण के लिए, यदि आप "www.adobephotoshop.com" पर जाते हैं और यह आपको "www.adobe.com" पर रीडायरेक्ट करता है) और किस प्रकार नहीं हैं (उदाहरण के लिए, अगर मैं "www.applecom" पर जाता हूं और यह मुझे "search.dnsassist.verizon.net" पर रीडायरेक्ट करता है। मैं काफी संकीर्ण समस्या के बारे में चिंतित हो सकता हूं (जो मेरे आईएसपी के कारण मुझे प्रभावित करता है), लेकिन यह सोचने के लिए कुछ है।

+0

पर नियंत्रण कैसे करें बहुत बहुत धन्यवाद! कस्टम UIView में पूरी तरह से काम करें। – Jack

+0

@CaoQuy वैसे, मैंने अपने उत्तर को एक सूक्ष्म पुनर्निर्देशन समस्या के साथ अद्यतन किया है, जहां कुछ आईएसपी (विशेष रूप से वेरिज़ोन) DNS विफलताओं को रोकते हैं और आपको अपने स्वयं के खोज पृष्ठ पर रीडायरेक्ट करते हैं। आप तय कर सकते हैं कि आपको इससे निपटने की आवश्यकता नहीं है, लेकिन मैं इसे पूर्ण प्रकटीकरण के हित में प्रस्तुत करता हूं। आईबी में – Rob

+0

@ रोब, क्या आपको UIWebView को प्रतिनिधि के साथ-साथ काम करने के लिए कनेक्ट करना होगा? – Supertecnoboff

संबंधित मुद्दे