iOS WKWebView loadHTMLString 異步加載圖片 為圖片添加點擊事件

本文主要是針對后臺返回數(shù)據(jù)是 html 標簽的數(shù)據(jù)加載

異步加載 html 標簽內(nèi)的 img 標簽掠手,給 img 標簽添加點擊事件


例如返回的數(shù)據(jù)格式如下

<div>
  一谅阿、《望天門山》 作者:唐代李白 1蛮放、原文
  天門中斷楚江開拍皮,碧水東流至此回。兩岸青山相對出贿堰,孤帆一bai片日邊來辙芍。 2、譯文
  天門山從中間斷裂是楚江把它沖開羹与,碧水向東浩然奔流到這里折回故硅。
  兩岸高聳的青山隔著長江相峙而立,江面上一葉孤舟像從日邊駛來纵搁。
  <img
    src="https://wx2.sinaimg.cn/large/006CHHsBly1gkxrs7785ej31402eoe84.jpg"
  />
</div>

或者

完整的 html 標簽數(shù)據(jù)

這些數(shù)據(jù)一般都是使用了富文本編輯器編輯的內(nèi)容吃衅,而且各種標簽樣式都有可能使用到,所以最好還是使用 WKWebView 來加載诡渴!
但是如果內(nèi)容含有 img 標簽的話就會等待所有的圖片加載完才會展示出整體的樣式捐晶,這樣比較影響體驗菲语。
所以應該考慮異步加載圖片,而不影響文字等標簽樣式的展示惑灵。

Demo下載

1.先將圖片鏈接中的 scheme 替換為自定義的 scheme

- (void)changeImageScheme {
    self.htmlString = [self.htmlString stringByReplacingOccurrencesOfString:self.oriImageUrl withString:self.xxxCustomImageUrl];
}

2.在 html 標簽中添加函數(shù)

- (void)addJsScript {
    
    NSString *htmlLab = @"</html>";
    NSString *scriptLab1 = @"</script>";
    
    NSString *jsFunctionString = @"function xxxGetAllImg() { return document.getElementsByTagName(\"img\"); }\
    function xxxUpdateImage(url, imgData) {  var list = Array.from(xxxGetAllImg()); for (let item of list) {  if ((item.src == url)) { item.src = imgData;   break; } } }        ";

    
    if (![self.htmlString containsString:htmlLab]) {
        [self addHtmlLab];
    }
    
    
    if ([self.htmlString containsString:scriptLab1]) {
     
        NSString *scriptString = [NSString stringWithFormat:@"%@%@",jsFunctionString,scriptLab1];
        self.htmlString = [self.htmlString stringByReplacingOccurrencesOfString:scriptLab1 withString:scriptString];
        
    }else {
        NSString *scriptLab0 = @"<script>";
        NSString *scriptString = [NSString stringWithFormat:@"%@%@%@%@",scriptLab0,jsFunctionString,scriptLab1,htmlLab];
        self.htmlString = [self.htmlString stringByReplacingOccurrencesOfString:htmlLab withString:scriptString];
    }
}

3.定義一個實現(xiàn) WKURLSchemeHandler 協(xié)議的類

@interface XXXCustomSchemeHanlder : NSObject <WKURLSchemeHandler>

@property (nonatomic, copy) NSString *oriImageUrl;
@property (nonatomic, copy) NSString *oriImageScheme;
@property (nonatomic, strong) UIImage *placeholderImage;
@property (nonatomic, copy) void(^updateImageBlock)(void);

@end

4.實現(xiàn)協(xié)議方法 用于攔截圖片加載


- (void)webView:(nonnull WKWebView *)webView startURLSchemeTask:(nonnull id<WKURLSchemeTask>)urlSchemeTask {


    UIImage *image = self.placeholderImage;
    NSData *data = UIImageJPEGRepresentation(image, 1.0);
    NSURLResponse *response = [[NSURLResponse alloc] initWithURL:urlSchemeTask.request.URL MIMEType:@"image/jpeg" expectedContentLength:data.length textEncodingName:nil];
    [urlSchemeTask didReceiveResponse:response];
    [urlSchemeTask didReceiveData:data];
    [urlSchemeTask didFinish];
    
    
    if (self.updateImageBlock) {
        self.updateImageBlock();
    }
    
    NSString *htmlImageUrlStr = [NSString stringWithFormat:@"%@",urlSchemeTask.request.URL];
    NSString *dloadImageUrlStr = [htmlImageUrlStr stringByReplacingOccurrencesOfString:XXXCustomImageScheme withString:self.oriImageScheme];
    
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        
        [self readImageForKey:dloadImageUrlStr htmlImageUrlStr:htmlImageUrlStr webView:webView];
    });
}




- (void)readImageForKey:(NSString *)dloadImageUrlStr htmlImageUrlStr:(NSString *)htmlImageUrlStr webView:(WKWebView *)webView {
    
    __weak typeof(self) weakSelf = self;
    NSURL *url = [NSURL URLWithString:dloadImageUrlStr];
    [[SDWebImageManager sharedManager] loadImageWithURL:url options:SDWebImageRetryFailed progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
        if (image || data) {
            NSData *imgData = data;
            if (!imgData) {
                imgData = UIImageJPEGRepresentation(image, 1);
            }
            
            dispatch_async(dispatch_get_main_queue(), ^{
                [weakSelf callJsUpdateImage:webView imageData:imgData htmlImageUrlStr:htmlImageUrlStr];
            });
            
        }
        if (error) {

        }
    }];
}




- (void)callJsUpdateImage:(WKWebView *)webView imageData:(NSData *)imageData htmlImageUrlStr:(NSString *)imageUrlString {
    
    __weak typeof(self) weakSelf = self;
    NSString *imageDataStr = [NSString stringWithFormat:@"data:image/png;base64,%@",[imageData base64EncodedString]];
    NSString *func = [NSString stringWithFormat:@"xxxUpdateImage('%@','%@')",imageUrlString,imageDataStr];
    [webView evaluateJavaScript:func completionHandler:^(id _Nullable response, NSError * _Nullable error) {
        if (weakSelf.updateImageBlock && !error) {
            weakSelf.updateImageBlock();
        }
    }];
    
}

5.初始化 WKWebView 并配置攔截信息

WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
XXXCustomSchemeHanlder *schemeHandler = XXXCustomSchemeHanlder.new;

schemeHandler.oriImageScheme = self.oriImageScheme;
schemeHandler.oriImageUrl = self.oriImageUrl;
schemeHandler.placeholderImage = self.placeholderImage;

__weak typeof(self) weakSelf = self;
schemeHandler.updateImageBlock = ^ {
    [weakSelf updateHeight];
};
[config setURLSchemeHandler:schemeHandler forURLScheme:XXXCustomImageScheme];


WKWebView  *webView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, self.width, self.height) configuration:config];

6. 更新高度


- (void)updateHeight {
    [self nowUpdateHeight];
    [self delayUpdateHeight];
}

- (void)nowUpdateHeight {
    
    __weak typeof(self) weakSelf = self;
    [self.webView evaluateJavaScript:@"document.body.offsetHeight" completionHandler:^(id _Nullable result,NSError * _Nullable error) {
        
        // 高度會有一點少 山上,手動補上 20
        CGFloat height = [result floatValue] + 20.0;
        weakSelf.webView.height = height;
        weakSelf.height = height;
        if (weakSelf.loadOverHeight) {
            weakSelf.loadOverHeight(height);
        }
    }];
}

- (void)delayUpdateHeight {
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, DelayTime * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        [self nowUpdateHeight];
    });
}

Demo下載

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市英支,隨后出現(xiàn)的幾起案子佩憾,更是在濱河造成了極大的恐慌,老刑警劉巖干花,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妄帘,死亡現(xiàn)場離奇詭異,居然都是意外死亡池凄,警方通過查閱死者的電腦和手機抡驼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來肿仑,“玉大人致盟,你說我怎么就攤上這事∮任浚” “怎么了馏锡?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長伟端。 經(jīng)常有香客問我杯道,道長,這世上最難降的妖魔是什么责蝠? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任党巾,我火速辦了婚禮,結果婚禮上玛歌,老公的妹妹穿的比我還像新娘昧港。我一直安慰自己擎椰,他們只是感情好支子,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著达舒,像睡著了一般值朋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上巩搏,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天昨登,我揣著相機與錄音,去河邊找鬼贯底。 笑死丰辣,一個胖子當著我的面吹牛撒强,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播笙什,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼飘哨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了琐凭?” 一聲冷哼從身側響起芽隆,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎统屈,沒想到半個月后胚吁,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡愁憔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年腕扶,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吨掌。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡蕉毯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出思犁,到底是詐尸還是另有隱情代虾,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布激蹲,位于F島的核電站棉磨,受9級特大地震影響,放射性物質發(fā)生泄漏学辱。R本人自食惡果不足惜乘瓤,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望策泣。 院中可真熱鬧衙傀,春花似錦、人聲如沸萨咕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽危队。三九已至聪建,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間茫陆,已是汗流浹背金麸。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留簿盅,地道東北人挥下。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓揍魂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親棚瘟。 傳聞我的和親對象是個殘疾皇子愉烙,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容