APP中调用网页的情况很多,常规情况下不需要我们考虑任何处理,直接加载即可。可是功能需要较为严格的时候,就需要前端的你设置准确的处理,以达到更好的用户体验。尤其是需要判断状态码的时候,需要注意了。
获取statusCode的正确姿势
一般情况下正常加载网页返回的statusCode都是200,当然,也会有404、400之类的情况,但是有一点要注意了,返回404这种状态码的时候,UIWebView的回调方法- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error;
是不会走的,因为web成功load的,只是服务端返回错误码而已。因此要注意,需要通过单独的方法而不是通过UIWebView的回调方法来获取statusCode,通过查阅资料,网上大多数的方法都是通过:
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil]; NSLog(@"statusCode:%ld", response.statusCode);
来获取response的状态码,可是笔者经过反复测试得不到正确结果,查看源码发现在iOS9之后此方法已经废弃,官方解释:
"Use [NSURLSession dataTaskWithRequest:completionHandler:] (see NSURLSession.h"
所以,别说了,弃之。
来看看最新的方法:
NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError *_Nullable error) { NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response; NSLog(@"statusCode:%ld", httpResponse.statusCode); }]; [dataTask resume];
当然了,该方法是放在[_webView loadRequest:request];
之前,还是放在UIWebView的回调方法中,根据实际需要就行。
其实,如果你在用三方AFNetworking,并且经历过2.0到3.0的更新,那么你会发现它也是在这方面进行了大变革。
不同状态码的前端处理
statusCode已经获取到了,后期处理就简单了。
呵呵。
有时候,当网页的statusCode为类似404时,我们并不希望只显示“404 not found”。例如,笔者在加载网页时都是需要在请求头中添加参数token,如果token不对,后台会给我返回401,意思是登录失效,需要重新登录。此时则需要弹出登录框之类的刷新UI动作。
if (httpResponse.statusCode == 401) { // 弹出登录框 }
当statusCode=401时,网页加载半天,弹出登录框的方法也已经走了,不过弹出框直到最后才弹出。
经过反复测试,笔者才发现问题,原来在block中的刷新UI在这种情况下是需要把该方法添加到主线程中的,加载速度恢复,贴上代码:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { // 获取返回的状态吗 NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError *_Nullable error) { NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response; NSLog(@"statusCode:%ld", httpResponse.statusCode); if (httpResponse.statusCode == 401) { dispatch_sync(dispatch_get_main_queue(), ^{ // 弹出登录框 }); }); } }]; [dataTask resume]; return YES; }