從零開始設(shè)計(jì)搭建ios App框架(十二)

熱修復(fù)


iOS應(yīng)用審核時(shí)間之長(zhǎng),只叫人不堪忍受;但是更讓人捶胸的是,App好不容易上線了,結(jié)果發(fā)現(xiàn)上線的APP有明顯的bug。真他NND,各種無語,各種不是滋味。這個(gè)時(shí)候會(huì)想有沒有不發(fā)布新版本解決類似這些小Bug,其實(shí)網(wǎng)上搜索一下,已經(jīng)有很多方案了。如JSPatch和WaxPatch。具體這兩個(gè)方案的原理可以參考:http://m.itdecent.cn/p/41ed877aa0cd 這里不細(xì)說了,本文使用的是JSPatch來完成App熱修復(fù)模塊的邏輯。

我認(rèn)為下載完補(bǔ)丁能夠修復(fù)Bug,同時(shí)還要防止補(bǔ)丁有bug,要能夠?qū)σ呀?jīng)下載到本地的補(bǔ)丁進(jìn)行刪除重新修復(fù)。這樣補(bǔ)丁就應(yīng)該要有編號(hào)。

#import "PGBaseObj.h"

/**
 補(bǔ)丁,用于熱修復(fù)
 */
@interface PGPatchObject : PGBaseObj
/*
 補(bǔ)丁ID
 */
@property(nonatomic, strong)NSString *mFixID;
/*
 補(bǔ)丁js腳本
 */
@property(nonatomic, strong)NSString *mFixString;

@end

補(bǔ)丁模塊作統(tǒng)一的管理(下載,緩存本地、刪除等)

@interface PGPatchManager : NSObject

+ (PGPatchManager *)shareInstance;

/*
 其實(shí)執(zhí)行是 [JPEngine startEngine]
 */
- (void)startListen;

/*
 執(zhí)行本要的腳本
 */
- (void)executeLocalHot;

/*
 從服務(wù)器上獲取新的腳本
 */
- (void)getHotData;

@end

獲取新的補(bǔ)丁時(shí)需將本地已經(jīng)存在的補(bǔ)丁作入?yún)⒏嬷?wù)器,請(qǐng)求到新補(bǔ)丁的處理邏輯如下:

static PGPatchManager *s_patchManager = nil;

@interface PGPatchManager ()<PGApiDelegate>
@property(nonatomic, strong)NSMutableArray *arrayHots;
@end

@implementation PGPatchManager

+ (PGPatchManager *)shareInstance
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        s_patchManager = [[PGPatchManager alloc] init];
        s_patchManager.arrayHots = [[NSMutableArray alloc] init];
        [s_patchManager.arrayHots addObjectsFromArray:[s_patchManager localHots]];
    });
    return s_patchManager;
}

- (void)startListen
{
    [JPEngine startEngine];
}

- (void)getHotData
{
    NSMutableArray *localHotIDs = [[NSMutableArray alloc] init];
    for(PGPatchObject *obj in self.arrayHots)
    {
        [localHotIDs addObject:obj.mFixID];
    }
    
    //本地已經(jīng)存在的補(bǔ)丁
    NSString *ids = [NSString jsonStringWithArray:localHotIDs];
    
    [PGRequestManager startPostClient:API_TYPE_PATCH param:@{@"fixIds":ids} target:self extendParam:nil];
}

- (NSMutableArray *)localHots
{
    NSObject *obj = [PGCacheManager readCacheType:ECacheType_Hots];
    if(obj != nil)
        return (NSMutableArray *)obj;
    else
        return [[NSMutableArray alloc] init];
}

- (void)saveHotsToLocal
{
    [PGCacheManager cacheData:self.arrayHots type:ECacheType_Hots];
}

- (void)executeLocalHot
{
    for(PGPatchObject *obj in self.arrayHots)
    {
        [JPEngine evaluateScript:obj.mFixString];
    }
}

- (void)executeHot:(NSArray *)array
{
    for(PGPatchObject *obj in array)
    {
        [JPEngine evaluateScript:obj.mFixString];
    }
}

- (void)addHot:(NSArray *)array
{
    if(array == nil || array.count <= 0)
        return;
    
    for(PGPatchObject *newobj in array)
    {
        for(PGPatchObject *obj in self.arrayHots)
        {
            if([newobj.mFixID compare:obj.mFixID] != NSOrderedSame)
            {
                [self.arrayHots addObject:obj];
            }
        }
    }
    
}

- (void)delHot:(NSArray *)array
{
    if(array == nil || array.count <= 0)
        return;
    
    for(PGPatchObject *delobj in array)
    {
        for(PGPatchObject *obj in self.arrayHots)
        {
            if([delobj.mFixID compare:obj.mFixID] == NSOrderedSame)
            {
                [self.arrayHots removeObject:obj];
                break;
            }
        }
    }
    
}

#pragma mark -
- (void)dataRequestFinish:(PGResultObject *)resultObj apiType:(PGApiType)apiType
{
    if(apiType == API_TYPE_PATCH)
    {
        if(resultObj.nCode == 0)
        {
            NSMutableDictionary *dic = (NSMutableDictionary *)resultObj.dataObject;
            NSMutableArray *addarray = [dic objectForKey:@"add"];
            NSMutableArray *delarray = [dic objectForKey:@"del"];
            
            //執(zhí)行新的補(bǔ)丁
            [self executeHot:addarray];
            
            //刪除舊的補(bǔ)丁
            [self delHot:delarray];
            
            //添加新的補(bǔ)丁
            [self addHot:addarray];
            
            //保存新的補(bǔ)丁
            [self saveHotsToLocal];
        }
    }
}

@end

基本邏輯就是這樣,完善的話,需對(duì)補(bǔ)丁進(jìn)行安全加密,網(wǎng)絡(luò)傳輸過程,本地存儲(chǔ)時(shí)最好都考慮一下安全性。我代碼里面是沒有作加密處理的,可別學(xué)我哦。

本也想畫一個(gè)補(bǔ)丁的修復(fù)邏輯流程圖,但發(fā)現(xiàn)前人已經(jīng)有現(xiàn)成的,我就不畫了,其實(shí)是我比較懶。流程圖可參考:http://blog.csdn.net/zm53373581/article/details/50011521

上一節(jié):消息推送
下一節(jié):webView封裝

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,351評(píng)論 25 708
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,694評(píng)論 4 61
  • 1. 種樹的最佳時(shí)間是25年前。僅次于它的最佳時(shí)間是現(xiàn)在。 大概是我20歲的時(shí)候,大學(xué)時(shí)期的我正處于一個(gè)人生的迷茫...
    安易_閱讀 3,586評(píng)論 32 110
  • 貓的尷尬-鄭彥芳 我是一只愛吃胡蘿卜的灰色貓,我不知道我是什么品種,媽媽在看弗洛伊德心理學(xué)說是為了我,怕我將來會(huì)變...
    我是彥芳閱讀 133評(píng)論 0 0
  • 無聊時(shí)聽首歌,這樣的自我放松和調(diào)節(jié)方式可能比吃有機(jī)食品還健康吧,but——有些歌,真心搞不懂是在講什么,今天...
    大李杜閱讀 512評(píng)論 0 0

友情鏈接更多精彩內(nèi)容