iOS-H5離線包本地緩存CCCandyWebCache

一、離線包緩存的簡(jiǎn)介

離線包緩存含幾個(gè)包的概念:
  1. 預(yù)裝包:指通過腳本文件在程序編譯時(shí)期下載的包阐斜。
  2. 增量包:指通過包的文件比對(duì)躯枢,生成的diff文件(差量包)
  3. 全量包:指完整的包文件
CCCandyWebCache離線包緩存的邏輯
  1. 第一次啟動(dòng)的時(shí)候先請(qǐng)求預(yù)裝包接口安裝預(yù)裝包,同時(shí)將預(yù)裝包請(qǐng)求的response配置表放在本地中舷丹,獲取預(yù)裝包zip的文件名字氓奈,先去判斷是否在預(yù)裝包配置表里面翘魄,然后判斷預(yù)裝包文件的MD5值和預(yù)裝包配置表fullPackageMD5是否匹配。如果信息都匹配上則將預(yù)裝包移動(dòng)到指定的本地目錄下(....../webapps/res/),然后解壓預(yù)裝包zip文件舀奶。
  2. 預(yù)裝包解壓成功后暑竟,會(huì)將本地包的信息組裝成body去請(qǐng)求檢查更新接口,將返回的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)模型育勺,根據(jù)state判斷是否需要更新光羞,如果要的話去判斷是全量更新還是增量更新。然后和本地?cái)?shù)據(jù)庫(kù)的模塊名字對(duì)比是否有匹配怀大,有的話判斷該包是否正在更新或者有其他錯(cuò)誤狀態(tài),如果狀態(tài)是正確的則使用版本號(hào)做對(duì)比呀闻,看是否需要更新包化借,如果服務(wù)器返回?cái)?shù)據(jù)的版本號(hào)更大則去更新資源。
  3. 如果是增量更新捡多,將diff文件下載下來后蓖康,將其MD5值與請(qǐng)求更新的response的對(duì)應(yīng)模塊的MD5值做匹配,匹配失敗則做全量更新,如果匹配成功則開始增量合并垒手,如果本地老的資源zip包已經(jīng)不存在則增量合并失敗蒜焊,做全量更新。如果增量包合并失敗則進(jìn)行全量更新科贬。增量包合并成功則解壓zip包泳梆,替換掉原來的解壓后的文件。資源更新成功清除內(nèi)存緩存榜掌。
  4. 全量更新优妙,下載成功后,匹配zip包的MD5值憎账,如果成功則移除原來的模塊文件套硼,然后進(jìn)行解壓。
  5. 每次啟動(dòng)都會(huì)去請(qǐng)求檢查更新這個(gè)接口胞皱,判斷資源是否需要更新邪意。
  6. 攔截的URl的時(shí)候九妈,先判斷URL 是否包含本地存儲(chǔ)的domain,包含則進(jìn)行本地資源匹配雾鬼,然后匹配上則去加載本地的html,css萌朱,js,等文件呆贿。否則正常去請(qǐng)求這個(gè)URL嚷兔。

二、集成SDK遇到的坑

  • 1.因?yàn)槭褂胹wift項(xiàng)目做入,pod是動(dòng)態(tài)庫(kù)冒晰,所以需要用本地庫(kù)去pod

1.SDK的podspec 去掉了作者信息,導(dǎo)致pod不成功.所以要加上
2.SDK的podspec ,homepage 指向不對(duì)竟块,導(dǎo)致pod不成功.
3. SDK的podspec 用了ZipArchive第三方庫(kù)但沒有指明依賴關(guān)系壶运,導(dǎo)致pod不成功.
  • 2.預(yù)裝包解析字段不正確

CCCacheManger 360行 開始  // 字段不正確
appVersionInfos -> resInfos
appId -> resID
Version -> resVersion

info.domains = [dic objectForKey:@"domains"];  // 取值不正確
// 更換如下:
if (dic[@"userData"]) {
    info.domains = [dic[@"userData"] objectForKey:@"domains"];
  } 
  • 3.字段fullMD5服務(wù)器要進(jìn)行Des加密+Base64,因?yàn)镾DK對(duì)fullMD5進(jìn)行了Base64 decodo 和 Des解密

  • 4.預(yù)裝包和檢查更新是post請(qǐng)求

  • 5.檢查更新返回的response 解析數(shù)據(jù)不正常導(dǎo)致 crash

HTResourceVersionChecker 214行 SDK模型里面的userData 是字符串 這里是Data類型 
  • 6.由于CCCancahce 是正對(duì)UIWebView做的緩存浪秘,而我們項(xiàng)目是WKWebView 蒋情,所以攔截不到網(wǎng)頁的請(qǐng)求,需要做一些處理 添加NSURLProtocol+WebKitSupport 這個(gè)類耸携,才可以攔截WKWebView的網(wǎng)絡(luò)請(qǐng)求

// .h文件
#import <Foundation/Foundation.h>

@interface NSURLProtocol (WebKitSupport)

+ (void)wk_registerScheme:(NSString*)scheme;

+ (void)wk_unregisterScheme:(NSString*)scheme;

@end 


// .m文件
#import "NSURLProtocol+WebKitSupport.h"
#import <WebKit/WebKit.h>

/**
 * The functions below use some undocumented APIs, which may lead to rejection by Apple.
 */

FOUNDATION_STATIC_INLINE Class ContextControllerClass() {
    static Class cls;
    if (!cls) {
        cls = [[[WKWebView new] valueForKey:@"browsingContextController"] class];
    }
    return cls;
}

FOUNDATION_STATIC_INLINE SEL RegisterSchemeSelector() {
    return NSSelectorFromString(@"registerSchemeForCustomProtocol:");
}

FOUNDATION_STATIC_INLINE SEL UnregisterSchemeSelector() {
    return NSSelectorFromString(@"unregisterSchemeForCustomProtocol:");
}

@implementation NSURLProtocol (WebKitSupport)

+ (void)wk_registerScheme:(NSString *)scheme {
    Class cls = ContextControllerClass();
    SEL sel = RegisterSchemeSelector();
    if ([(id)cls respondsToSelector:sel]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        [(id)cls performSelector:sel withObject:scheme];
#pragma clang diagnostic pop
    }
}

+ (void)wk_unregisterScheme:(NSString *)scheme {
    Class cls = ContextControllerClass();
    SEL sel = UnregisterSchemeSelector();
    if ([(id)cls respondsToSelector:sel]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        [(id)cls performSelector:sel withObject:scheme];
#pragma clang diagnostic pop
    }
}

@end
  • 7.增量更新MD5校驗(yàn)失敗棵癣,進(jìn)行全量更新,資源是更新但是沒有更新本地的version

 // 要在CCCandyWebCache  333行進(jìn)行新的版本賦值
NSArray* comps = [info.composeVersion componentsSeparatedByString:@"&"];
info.version = (comps.count == 2 ? comps[1] : comps[0]); 
  • 8.多個(gè)包domain應(yīng)該對(duì)應(yīng)于ResID 的目錄名 而不是域名夺衍,要不然多個(gè)離線包會(huì)有問題狈谊。

 // 如 https://www.baicu.com/feature/task
// feature/task 是zip包解壓后的文件目錄
  • 9.攔擊到的URL匹配規(guī)則有問題,要截取到domain的域名去拼接路徑沟沙,然后去匹配本地是否有緩存河劝。

 // CCCacheManager 187行
[_domainWebappInfos enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull domain, CCWebAppInfo * _Nonnull webappInfo, BOOL * _Nonnull stop) {
            NSString *domainLastObject = [domain componentsSeparatedByString:@"://"].lastObject;
            if ([url hasPrefix:domainLastObject]) {
                if (webappInfo.status != CCWebAppStatusAvailable) {
                    CCLogWarn(@"[CCCacheManager]:資源正在更新或已出錯(cuò),請(qǐng)求不使用緩存,url==>:%@矛紫。",url);
                }
                if (url.length > domainLastObject.length) {
                    NSString *domainOrigin = [domainLastObject componentsSeparatedByString:@"/"].firstObject;
                    key = [NSString stringWithFormat:@"%@/%@",webappInfo.name,[url substringFromIndex:domainOrigin.length+1]];
                }
                [_urlToKeyMapCache setObject:key forKey:url];
                *stop = YES;
            }
        }];


// CCCacheManager 174 對(duì) webView reload方法 低版本系統(tǒng)做兼容
NSArray* strs = [url componentsSeparatedByString:@"://"];
        if (strs.count == 2) {
            NSArray *strsurl = [strs[1] componentsSeparatedByString:@".html"];
            if (strsurl.count == 2 && [strsurl[1] isEqualToString:@"#/"]) {
               url = [strsurl[0] stringByAppendingString:@".html"];
            } else {
               url = strs[1];
            }
        }
  • 10.移除緩存下載進(jìn)度觀察者 不能放在deinit方法里面 要不然會(huì)影響內(nèi)存泄漏赎瞎,添加和移除要放在viewWillAppear 和 viewWillDisappear方法里面

  • 11.緩存url不支持帶?號(hào)訪問

  • 12.增量或全量更新判斷條件不正確

 //  CCCandyWebCache.m 206行
  webappInfo.isDiffTask = _diffEnable ? (versionInfo.diffUrl.length  ? YES : NO) : NO; 
// 更換如下:
  webappInfo.isDiffTask = _diffEnable ? (versionInfo.diffUrl.length > 0 ? YES : NO) : NO;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市颊咬,隨后出現(xiàn)的幾起案子务甥,更是在濱河造成了極大的恐慌,老刑警劉巖喳篇,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缓呛,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡杭隙,警方通過查閱死者的電腦和手機(jī)哟绊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人票髓,你說我怎么就攤上這事攀涵。” “怎么了洽沟?”我有些...
    開封第一講書人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵以故,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我裆操,道長(zhǎng)怒详,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任踪区,我火速辦了婚禮昆烁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缎岗。我一直安慰自己静尼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開白布传泊。 她就那樣靜靜地躺著鼠渺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪眷细。 梳的紋絲不亂的頭發(fā)上拦盹,一...
    開封第一講書人閱讀 51,737評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音溪椎,去河邊找鬼普舆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛池磁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播楷兽,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼地熄,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了芯杀?” 一聲冷哼從身側(cè)響起端考,我...
    開封第一講書人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎揭厚,沒想到半個(gè)月后却特,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡筛圆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年裂明,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片太援。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡闽晦,死狀恐怖扳碍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仙蛉,我是刑警寧澤笋敞,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站荠瘪,受9級(jí)特大地震影響夯巷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜哀墓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一趁餐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧麸祷,春花似錦澎怒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至走孽,卻和暖如春惧辈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背磕瓷。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工盒齿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人困食。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓边翁,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親硕盹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子符匾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

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

  • ORA-00001: 違反唯一約束條件 (.) 錯(cuò)誤說明:當(dāng)在唯一索引所對(duì)應(yīng)的列上鍵入重復(fù)值時(shí),會(huì)觸發(fā)此異常瘩例。 O...
    我想起個(gè)好名字閱讀 5,321評(píng)論 0 9
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,105評(píng)論 1 32
  • 點(diǎn)擊查看原文 Web SDK 開發(fā)手冊(cè) SDK 概述 網(wǎng)易云信 SDK 為 Web 應(yīng)用提供一個(gè)完善的 IM 系統(tǒng)...
    layjoy閱讀 13,769評(píng)論 0 15
  • API定義規(guī)范 本規(guī)范設(shè)計(jì)基于如下使用場(chǎng)景: 請(qǐng)求頻率不是非常高:如果產(chǎn)品的使用周期內(nèi)請(qǐng)求頻率非常高啊胶,建議使用雙通...
    有涯逐無涯閱讀 2,548評(píng)論 0 6
  • feisky云計(jì)算、虛擬化與Linux技術(shù)筆記posts - 1014, comments - 298, trac...
    不排版閱讀 3,855評(píng)論 0 5