av一区二区在线观看_亚洲男人的天堂网站_日韩亚洲视频_在线成人免费_欧美日韩精品免费观看视频_久草视

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

iOS WKWebview 白屏檢測(cè)實(shí)現(xiàn)的示例

瀏覽:17日期:2022-09-17 08:22:41

前言

自ios8推出wkwebview以來(lái),極大改善了網(wǎng)頁(yè)加載速度及內(nèi)存泄漏問題,逐漸全面取代笨重的UIWebview。盡管高性能、高刷新的WKWebview在混合開發(fā)中大放異彩表現(xiàn)優(yōu)異,但加載網(wǎng)頁(yè)過程中出現(xiàn)異常白屏的現(xiàn)象卻仍然屢見不鮮,且現(xiàn)有的api協(xié)議處理捕捉不到這種異常case,造成用戶無(wú)用等待體驗(yàn)很差。 針對(duì)業(yè)務(wù)場(chǎng)景需求,實(shí)現(xiàn)加載白屏檢測(cè)??紤]采用字節(jié)跳動(dòng)團(tuán)隊(duì)提出的webview優(yōu)化技術(shù)方案。在合適的加載時(shí)機(jī)對(duì)當(dāng)前webview可視區(qū)域截圖,并對(duì)此快照進(jìn)行像素點(diǎn)遍歷,如果非白屏顏色的像素點(diǎn)超過一定的閾值,認(rèn)定其為非白屏,反之重新加載請(qǐng)求。

獲取快照

ios官方提供了簡(jiǎn)易的獲取webview快照接口,通過異步回調(diào)拿到當(dāng)前可視區(qū)域的屏幕截圖。

- (void)takeSnapshotWithConfiguration:(nullable WKSnapshotConfiguration *)snapshotConfiguration completionHandler:(void (^)(UIImage * _Nullable snapshotImage, NSError * _Nullable error))completionHandler API_AVAILABLE(ios(11.0));

其中snapshotConfiguration 參數(shù)可用于配置快照大小范圍,默認(rèn)截取當(dāng)前客戶端整個(gè)屏幕區(qū)域。由于可能出現(xiàn)導(dǎo)航欄成功加載而內(nèi)容頁(yè)卻空白的特殊情況,導(dǎo)致非白屏像素點(diǎn)數(shù)增加對(duì)最終判定結(jié)果造成影響,考慮將其剔除。

- (void)judgeLoadingStatus:(WKWebView *)webview { if (@available(iOS 11.0, *)) { if (webView && [webView isKindOfClass:[WKWebView class]]) { CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height; //狀態(tài)欄高度 CGFloat navigationHeight = webView.viewController.navigationController.navigationBar.frame.size.height; //導(dǎo)航欄高度 WKSnapshotConfiguration *shotConfiguration = [[WKSnapshotConfiguration alloc] init]; shotConfiguration.rect = CGRectMake(0, statusBarHeight + navigationHeight, _webView.bounds.size.width, (_webView.bounds.size.height - navigationHeight - statusBarHeight)); //僅截圖檢測(cè)導(dǎo)航欄以下部分內(nèi)容 [_webView takeSnapshotWithConfiguration:shotConfiguration completionHandler:^(UIImage * _Nullable snapshotImage, NSError * _Nullable error) {//todo }]; } }}

縮放快照

為了提升檢測(cè)性能,考慮將快照縮放至1/5,減少像素點(diǎn)總數(shù),從而加快遍歷速度。

- (UIImage *)scaleImage: (UIImage *)image { CGFloat scale = 0.2; CGSize newsize; newsize.width = floor(image.size.width * scale); newsize.height = floor(image.size.height * scale); if (@available(iOS 10.0, *)) { UIGraphicsImageRenderer * renderer = [[UIGraphicsImageRenderer alloc] initWithSize:newsize]; return [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) { [image drawInRect:CGRectMake(0, 0, newsize.width, newsize.height)]; }]; }else{ return image; }}

縮小前后性能對(duì)比(實(shí)驗(yàn)環(huán)境:iPhone11同一頁(yè)面下):

縮放前白屏檢測(cè):

iOS WKWebview 白屏檢測(cè)實(shí)現(xiàn)的示例

iOS WKWebview 白屏檢測(cè)實(shí)現(xiàn)的示例

耗時(shí)20ms

縮放后白屏檢測(cè):

iOS WKWebview 白屏檢測(cè)實(shí)現(xiàn)的示例

iOS WKWebview 白屏檢測(cè)實(shí)現(xiàn)的示例

耗時(shí)13ms

注意這里有個(gè)小坑。由于縮略圖的尺寸在 原圖寬高*縮放系數(shù)后可能不是整數(shù),在布置畫布重繪時(shí)默認(rèn)向上取整,這就造成畫布比實(shí)際縮略圖大(混蛋啊 摔?。T诒闅v縮略圖像素時(shí),會(huì)將圖外畫布上的像素納入考慮范圍,導(dǎo)致實(shí)際白屏頁(yè) 像素占比并非100% 如圖所示。因此使用floor將其尺寸大小向下取整。

遍歷快照

遍歷快照縮略圖像素點(diǎn),對(duì)白色像素(R:255 G: 255 B: 255)占比大于95%的頁(yè)面,認(rèn)定其為白屏。

- (BOOL)searchEveryPixel:(UIImage *)image { CGImageRef cgImage = [image CGImage]; size_t width = CGImageGetWidth(cgImage); size_t height = CGImageGetHeight(cgImage); size_t bytesPerRow = CGImageGetBytesPerRow(cgImage); //每個(gè)像素點(diǎn)包含r g b a 四個(gè)字節(jié) size_t bitsPerPixel = CGImageGetBitsPerPixel(cgImage); CGDataProviderRef dataProvider = CGImageGetDataProvider(cgImage); CFDataRef data = CGDataProviderCopyData(dataProvider); UInt8 * buffer = (UInt8*)CFDataGetBytePtr(data); int whiteCount = 0; int totalCount = 0; for (int j = 0; j < height; j ++ ) { for (int i = 0; i < width; i ++) { UInt8 * pt = buffer + j * bytesPerRow + i * (bitsPerPixel / 8); UInt8 red = * pt; UInt8 green = *(pt + 1); UInt8 blue = *(pt + 2);// UInt8 alpha = *(pt + 3); totalCount ++; if (red == 255 && green == 255 && blue == 255) {whiteCount ++; } } } float proportion = (float)whiteCount / totalCount ; NSLog(@'當(dāng)前像素點(diǎn)數(shù):%d,白色像素點(diǎn)數(shù):%d , 占比: %f',totalCount , whiteCount , proportion ); if (proportion > 0.95) { return YES; }else{ return NO; }}

總結(jié)

typedef NS_ENUM(NSUInteger,webviewLoadingStatus) { WebViewNormalStatus = 0, //正常 WebViewErrorStatus, //白屏 WebViewPendStatus, //待決};// 判斷是否白屏- (void)judgeLoadingStatus:(WKWebview *)webview withBlock:(void (^)(webviewLoadingStatus status))completionBlock{ webviewLoadingStatus __block status = WebViewPendStatus; if (@available(iOS 11.0, *)) { if (webview && [webview isKindOfClass:[WKWebView class]]) { CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height; //狀態(tài)欄高度 CGFloat navigationHeight = webview.viewController.navigationController.navigationBar.frame.size.height; //導(dǎo)航欄高度 WKSnapshotConfiguration *shotConfiguration = [[WKSnapshotConfiguration alloc] init]; shotConfiguration.rect = CGRectMake(0, statusBarHeight + navigationHeight, webview.bounds.size.width, (webview.bounds.size.height - navigationHeight - statusBarHeight)); //僅截圖檢測(cè)導(dǎo)航欄以下部分內(nèi)容 [webview takeSnapshotWithConfiguration:shotConfiguration completionHandler:^(UIImage * _Nullable snapshotImage, NSError * _Nullable error) {if (snapshotImage) { CGImageRef imageRef = snapshotImage.CGImage; UIImage * scaleImage = [self scaleImage:snapshotImage]; BOOL isWhiteScreen = [self searchEveryPixel:scaleImage]; if (isWhiteScreen) { status = WebViewErrorStatus; }else{ status = WebViewNormalStatus; }}if (completionBlock) { completionBlock(status);} }]; } }}// 遍歷像素點(diǎn) 白色像素占比大于95%認(rèn)定為白屏- (BOOL)searchEveryPixel:(UIImage *)image { CGImageRef cgImage = [image CGImage]; size_t width = CGImageGetWidth(cgImage); size_t height = CGImageGetHeight(cgImage); size_t bytesPerRow = CGImageGetBytesPerRow(cgImage); //每個(gè)像素點(diǎn)包含r g b a 四個(gè)字節(jié) size_t bitsPerPixel = CGImageGetBitsPerPixel(cgImage); CGDataProviderRef dataProvider = CGImageGetDataProvider(cgImage); CFDataRef data = CGDataProviderCopyData(dataProvider); UInt8 * buffer = (UInt8*)CFDataGetBytePtr(data); int whiteCount = 0; int totalCount = 0; for (int j = 0; j < height; j ++ ) { for (int i = 0; i < width; i ++) { UInt8 * pt = buffer + j * bytesPerRow + i * (bitsPerPixel / 8); UInt8 red = * pt; UInt8 green = *(pt + 1); UInt8 blue = *(pt + 2);// UInt8 alpha = *(pt + 3); totalCount ++; if (red == 255 && green == 255 && blue == 255) {whiteCount ++; } } } float proportion = (float)whiteCount / totalCount ; NSLog(@'當(dāng)前像素點(diǎn)數(shù):%d,白色像素點(diǎn)數(shù):%d , 占比: %f',totalCount , whiteCount , proportion ); if (proportion > 0.95) { return YES; }else{ return NO; }}//縮放圖片- (UIImage *)scaleImage: (UIImage *)image { CGFloat scale = 0.2; CGSize newsize; newsize.width = floor(image.size.width * scale); newsize.height = floor(image.size.height * scale); if (@available(iOS 10.0, *)) { UIGraphicsImageRenderer * renderer = [[UIGraphicsImageRenderer alloc] initWithSize:newsize]; return [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) { [image drawInRect:CGRectMake(0, 0, newsize.width, newsize.height)]; }]; }else{ return image; }}

僅需在合適的view生命周期內(nèi)回調(diào)使用該函數(shù)方法即可檢測(cè)出頁(yè)面狀態(tài)是否白屏,且性能損耗可忽略不計(jì)。

聲明

作者:BBTime鏈接:https://juejin.im/post/6885298718174609415

以上就是iOS WKWebview 白屏檢測(cè)實(shí)現(xiàn)的示例的詳細(xì)內(nèi)容,更多關(guān)于iOS WKWebview 白屏檢測(cè)的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: IOS
相關(guān)文章:
主站蜘蛛池模板: 亚洲欧美激情四射 | 国产一区二区在线免费视频 | 午夜影晥| 成人激情视频免费在线观看 | 午夜专区 | 久久久久久久99 | 国产第一亚洲 | 亚洲福利精品 | 黄色一级毛片免费看 | 亚洲国产日韩一区 | 国产亚洲第一页 | 亚洲国产精品久久久久婷婷老年 | 黑人巨大精品 | 中文字幕视频在线看5 | 日韩精品一区二区三区在线观看 | 欧美性吧| 狠狠视频 | 一级片在线观看 | 国产三区视频在线观看 | 国产 日韩 欧美 中文 在线播放 | 国产精品久久精品 | 久久久国产精品视频 | 久艹网站| 亚洲精品亚洲人成人网 | 一区二区三区国产 | 日本在线播放 | 欧美高清一级片 | 欧美一级大片免费观看 | 亚洲精品美女视频 | 日韩精品一区二区三区四区视频 | www.日本国产| 狠狠干av| 亚洲一级毛片 | 韩国理论电影在线 | 欧美一区二区三区四区视频 | 国产成人亚洲精品 | 亚洲免费婷婷 | 亚洲精品9999 | 亚洲综合色视频在线观看 | 99久久精品免费看国产小宝寻花 | 91婷婷韩国欧美一区二区 |