iOS全面支持webp格式圖片 Custom URLProtocol

iOS 全面支持 webp格式圖片 Custom URLProtocol

webp格式圖片

webp格式圖片是google推出的许昨,相比jpg png有著巨大的優(yōu)勢,同樣質(zhì)量的圖片webp格式的圖片占用空間更小赘来,在像電商這樣圖片比較多的App中,使用webp格式圖片會很有優(yōu)勢。

webp在iOS設(shè)備上

當前的iOS不支持webp棋电,不知道以后會不會支持振劳,所以從網(wǎng)絡(luò)上拿到一個webp格式的圖片后椎组,并不能直接顯示出來,需要把data數(shù)據(jù)轉(zhuǎn)化為jpg或者png來顯示历恐。

支持webp的方案

使用SDWebImage中帶的WebP

在podfile中加入

pod 'SDWebImage/WebP'

可以在SDWebImage中加入UIImage的WebP類別寸癌,同時會引入libwebp。在使用SD加載圖片時弱贼,會判定圖片的格式蒸苇,如果為webp,調(diào)用Google的libwebp庫進行解析吮旅。
調(diào)用過程如下:

sd_setImageWithURL -> 
URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error ->
sd_imageWithData->
sd_imageWithWebPData
處理成功后會返回一個UIImage溪烤。

在WebView中使用Webp格式圖片

如果有一些web頁中使用了webp格式的圖片,僅用上述方法是不行的,我推薦的做法是寫一個自定義的URLSession protocol, 繼承自NSURLProtocol, 然后注冊檬嘀。自定義的協(xié)議文件為DMCustomURLSessionProtocol這個類槽驶,整個工程的地址如下:Demo地址.
關(guān)鍵代碼如下:

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error{
   if (error == nil) {
        if ([task.currentRequest.URL.absoluteString hasSuffix:@"webp"]) {
            NSLog(@"webp will changed:%@",task.currentRequest.URL);
            UIImage *imgData = [UIImage sd_imageWithData:self.imageData];
            NSData *transData = UIImageJPEGRepresentation(imgData, 0.8f);
            self.beginAppendData = NO;
            self.imageData = nil;
            [self.client URLProtocol:self didLoadData:transData];
        }
        [self.client URLProtocolDidFinishLoading:self];
    } else if ( [[error domain] isEqual:NSURLErrorDomain] && ([error code] == NSURLErrorCancelled) ) {
        [self.client URLProtocol:self didFailWithError:error];
    }else{
        [[self client] URLProtocol:self didFailWithError:error];
    }
}

在一個task完成的時候,根據(jù)task中的url是否含有webp后綴鸳兽,做處理掂铐,如果有webp后綴,用SD轉(zhuǎn)化圖片贸铜,轉(zhuǎn)化完成后堡纬, 需要把beginAppendData置為NO,imageData置為nil蒿秦,self.client再load一次data烤镐。

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
    if ([dataTask.currentRequest.URL.absoluteString hasSuffix:@"webp"]) {
        self.beginAppendData = YES;
        [self.imageData appendData:data];
    }
    if (!_beginAppendData) {
        [self.client URLProtocol:self didLoadData:data];
    }
}

在didReceiveData里面要做一些處理,這里面是每次receive一塊新的data棍鳖,當一個請求的地址里面含有webp時炮叶,把beginAppendData置為yes,同時imgeData開始append data渡处,而這時self.client不load data镜悉,每次有新data來,imageData就append上医瘫,止到這一個請求完成侣肄, 在完成的里面 轉(zhuǎn)化webp后 load data。(請求一個圖片后醇份,可能在did receive data中收到多次才能收全稼锅。)

處理重定向

自定義URL Protocol時,一定要實現(xiàn)重定向的代理方法僚纷,不然矩距,在webview里面會出問題。

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)newRequest completionHandler:(void (^)(NSURLRequest *))completionHandler
{
    NSMutableURLRequest *    redirectRequest;
    
    redirectRequest = [newRequest mutableCopy];
    [[self class] removePropertyForKey:URLProtocolHandledKey inRequest:redirectRequest];
    
    [[self client] URLProtocol:self wasRedirectedToRequest:redirectRequest redirectResponse:response];
    
    [self.session invalidateAndCancel];
    [[self client] URLProtocol:self didFailWithError:[NSError errorWithDomain:NSCocoaErrorDomain code:NSUserCancelledError userInfo:nil]];
}

向URL加載系統(tǒng)注冊子類

最后在appdelegate didFinishLaunchingWithOptions中注冊上

 [NSURLProtocol registerClass:[DMCustomURLSessionProtocol class]];

當請求被加載時怖竭,系統(tǒng)會向每一個注冊過protocol詢問能否控制這個請求锥债,第一個通過+ canInitWithRequest:返回為YES的protocol會控制這個請求。URLprotocol會被以注冊順序的反序訪問.所以如果只處理webp的圖片痊臭,在canInitWithRequest需要限定好哮肚,可以這樣寫:

+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
    
    //只處理http和https請求
    NSString *scheme = [[request URL] scheme];
    if ( (([scheme caseInsensitiveCompare:@"http"] == NSOrderedSame ||
          [scheme caseInsensitiveCompare:@"https"] == NSOrderedSame)) && ([scheme hasSuffix:@"webp"]))
    {
        //看看是否已經(jīng)處理過了,防止無限循環(huán)
        if ([NSURLProtocol propertyForKey:URLProtocolHandledKey inRequest:request]) {
            return NO;
        }
        return YES;
    }
    return NO;
}

動態(tài)webp

SDWebImage 默認是不支持動態(tài)webp 格式圖片的广匙,4.0以后會支持允趟,目前還是 beta 版,可以 pod install 我的這個https://github.com/dulingkang/sd_webp,

pod 'sd_webp'

是用最新的3.8.2加入動態(tài) webp 支持的艇潭。

再發(fā)一下地址

  • 工程地址, DMCustomURLSessionProtocol這個類拼窥;

微信公眾號

開發(fā)者思維 devthinking

QQ交流群:295976280

iOS交流群(一)群二維碼.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末戏蔑,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子鲁纠,更是在濱河造成了極大的恐慌总棵,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件改含,死亡現(xiàn)場離奇詭異情龄,居然都是意外死亡,警方通過查閱死者的電腦和手機捍壤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門骤视,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鹃觉,你說我怎么就攤上這事专酗。” “怎么了盗扇?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵祷肯,是天一觀的道長。 經(jīng)常有香客問我疗隶,道長佑笋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任斑鼻,我火速辦了婚禮蒋纬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘坚弱。我一直安慰自己蜀备,他們只是感情好,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布史汗。 她就那樣靜靜地躺著琼掠,像睡著了一般拒垃。 火紅的嫁衣襯著肌膚如雪停撞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天悼瓮,我揣著相機與錄音戈毒,去河邊找鬼。 笑死横堡,一個胖子當著我的面吹牛埋市,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播命贴,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼道宅,長吁一口氣:“原來是場噩夢啊……” “哼食听!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起污茵,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤樱报,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后泞当,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體迹蛤,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年襟士,在試婚紗的時候發(fā)現(xiàn)自己被綠了盗飒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡陋桂,死狀恐怖逆趣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嗜历,我是刑警寧澤汗贫,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站秸脱,受9級特大地震影響落包,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜摊唇,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一咐蝇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧巷查,春花似錦有序、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至崇败,卻和暖如春盅称,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背后室。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工缩膝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人岸霹。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓疾层,卻偏偏與公主長得像,于是被迫代替她去往敵國和親贡避。 傳聞我的和親對象是個殘疾皇子痛黎,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

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