引言
问题的现象是 WKWebView 明明已经加载成功并完成了,还是调用了失败的代理方法,弹出了 toast。
正文
问题是如何发生的呢?先上代码:
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
[MBProgressHUD showError:NSLocalizedString(@"网络加载失败!", nil)];
}
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
[MBProgressHUD showError:NSLocalizedString(@"网络加载失败!", nil)];
}
因为最近一直在 iOS 12 以上的系统开发,开发过程中一直没有发现问题,到上传 AppStore 从 TestFlight 下载测试的时候,一个测试发现的问题。手机系统是 iOS 11.4.1,然后连上打断点调试,发现每次都会调用失败的代理方法。为什么呢?经过查资料发现原来是请求被 cancel 掉了。-999 的错误代码是 NSURLErrorCancelled,结合项目的实际流程,一开始加载 本地html 在接收到请求成功后,重新加载线上的 url, 只是为了让加载快一点,没想到还给自己挖坑了。
NS_ENUM(NSInteger)
{
NSURLErrorUnknown = -1,
NSURLErrorCancelled = -999,
NSURLErrorBadURL = -1000,
NSURLErrorTimedOut = -1001,
NSURLErrorUnsupportedURL = -1002,
NSURLErrorCannotFindHost = -1003,
NSURLErrorCannotConnectToHost = -1004,
NSURLErrorNetworkConnectionLost = -1005,
NSURLErrorDNSLookupFailed = -1006,
NSURLErrorHTTPTooManyRedirects = -1007,
NSURLErrorResourceUnavailable = -1008,
NSURLErrorNotConnectedToInternet = -1009,
NSURLErrorRedirectToNonExistentLocation = -1010,
NSURLErrorBadServerResponse = -1011,
NSURLErrorUserCancelledAuthentication = -1012,
NSURLErrorUserAuthenticationRequired = -1013,
NSURLErrorZeroByteResource = -1014,
NSURLErrorCannotDecodeRawData = -1015,
NSURLErrorCannotDecodeContentData = -1016,
NSURLErrorCannotParseResponse = -1017,
NSURLErrorAppTransportSecurityRequiresSecureConnection NS_ENUM_AVAILABLE(10_11, 9_0) = -1022,
NSURLErrorFileDoesNotExist = -1100,
NSURLErrorFileIsDirectory = -1101,
NSURLErrorNoPermissionsToReadFile = -1102,
NSURLErrorDataLengthExceedsMaximum NS_ENUM_AVAILABLE(10_5, 2_0) = -1103,
// SSL errors
NSURLErrorSecureConnectionFailed = -1200,
NSURLErrorServerCertificateHasBadDate = -1201,
NSURLErrorServerCertificateUntrusted = -1202,
NSURLErrorServerCertificateHasUnknownRoot = -1203,
NSURLErrorServerCertificateNotYetValid = -1204,
NSURLErrorClientCertificateRejected = -1205,
NSURLErrorClientCertificateRequired = -1206,
NSURLErrorCannotLoadFromNetwork = -2000,
// Download and file I/O errors
NSURLErrorCannotCreateFile = -3000,
NSURLErrorCannotOpenFile = -3001,
NSURLErrorCannotCloseFile = -3002,
NSURLErrorCannotWriteToFile = -3003,
NSURLErrorCannotRemoveFile = -3004,
NSURLErrorCannotMoveFile = -3005,
NSURLErrorDownloadDecodingFailedMidStream = -3006,
NSURLErrorDownloadDecodingFailedToComplete =-3007,
NSURLErrorInternationalRoamingOff NS_ENUM_AVAILABLE(10_7, 3_0) = -1018,
NSURLErrorCallIsActive NS_ENUM_AVAILABLE(10_7, 3_0) = -1019,
NSURLErrorDataNotAllowed NS_ENUM_AVAILABLE(10_7, 3_0) = -1020,
NSURLErrorRequestBodyStreamExhausted NS_ENUM_AVAILABLE(10_7, 3_0) = -1021,
NSURLErrorBackgroundSessionRequiresSharedContainer NS_ENUM_AVAILABLE(10_10, 8_0) = -995,
NSURLErrorBackgroundSessionInUseByAnotherProcess NS_ENUM_AVAILABLE(10_10, 8_0) = -996,
NSURLErrorBackgroundSessionWasDisconnected NS_ENUM_AVAILABLE(10_10, 8_0)= -997,
};
所以,解决方法就是在代理方法里面加一个判断,对,只是这一个方法:
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
// 如果是被取消,这里根据自身实际业务需求进行编辑
if (error.code == NSURLErrorCancelled) {
return;
}
[MBProgressHUD showError:NSLocalizedString(@"网络加载失败!", nil)];
}
注:如果是手动调用 WKWebView 的 stopLoading 方法,也会出发该代理方法。
结尾
一开始的时候提到了在 iOS 12 上并没有这个问题。对,因为 iOS WKWebView 在 iOS 12 进行了一些改变,比如 userAgent 等。所以在 iOS 12 上不会出现。
记录一下就当是提醒自己不要再写类似的 bug。