iOS熱修復(動態Framework)
來自: http://finalshares.com/read-6951
上次降到了利用jspatch實現熱修復,那么今天我就簡單說一下關于動態framework 來進行動態修復;
猶豫存在較復雜的解耦,所以我將整個app寫成一個Framework;
1、這里是一個比較簡單的app 首先需要寫一個管理類去管理分配這些資源,
/**
- 主程序和此動態庫的關系樞紐,也就是從“主程序”到“動態庫內封裝的程序”的入口方法 *
- @param rootViewController “主程序”中引導
@param bundle 此動態庫在document文件中的路徑,用于xib的加載和圖片的加載 */
- (void)bootLoader:(id)rootViewController WithBundle:(NSBundle *)bundle;</pre>
實現方法:
- (void)bootLoader:(id)rootViewController WithBundle:(NSBundle )bundle { / 初始化第一個管理Controller 這里的重點是xib文件的加載 通常我們在初始化xib的時候并不是很在意bundle:這個參數,一般情況下都會賦予nil值 其實我們所用到的圖片、xib等資源文件都是在程序內部中獲取的,也就是我們常用的[NSBundle mainBundle]中獲取,所謂的NSBundle本質上就是一個路徑,mainBundle指向的是.app下。 而如果我們不指定bundle,則會默認從.app路徑下去尋找資源。 不過很顯然,我們的動態庫是放到“主程序”的document文件下的,所以資源文件是不可能在[NSbundle mainBundle]中獲取到的,所以這里我們需要指定bundle參數,這也是傳遞framework的路徑的意義所在 / _currentBundle = bundle; [DataCenter shareCenter].bootLoader = bundle; HZRootViewController rooter = [[HZRootViewController alloc]initWithNibName:NSStringFromClass([HZRootViewController class]) bundle:bundle]; //保存NSBundle rooter.bootLoader = bundle;
[rootViewController presentViewController:rooter animated:YES completion:NULL];
[self setRootViewController: [DataCenter shareCenter].uToken ? YES : NO WithRooter:rooter];
- (void)bootLoader:(id)rootViewController WithBundle:(NSBundle *)bundle;</pre>
}</pre>
2、我們需要在app也就是這個程序殼里載入這部分代碼
- (void)setRooter { NSArray paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES); NSString documentDirectory = nil; if ([paths count] != 0) documentDirectory = [paths objectAtIndex:0];//拼接放到document中的framework路徑 NSString *libName = @"HZDelivery.framework"; NSString *destLibPath = [documentDirectory stringByAppendingPathComponent:libName]; //判斷一下有沒有這個文件的存在 如果沒有直接跳出 NSFileManager *manager = [NSFileManager defaultManager]; if (![manager fileExistsAtPath:destLibPath]) { NSLog(@"There isn't have the file"); return; } //復制到程序中 NSError *error = nil; //使用NSBundle加載動態庫 NSBundle *frameworkBundle = [NSBundle bundleWithPath:destLibPath]; if (frameworkBundle && [frameworkBundle load]) { NSLog(@"bundle load framework success."); }else { NSLog(@"bundle load framework err:%@",error); return; } /* *通過NSClassFromString方式讀取類 *PacteraFramework 為動態庫中入口類 */ Class pacteraClass = NSClassFromString(@"HZDeliveryManager"); if (!pacteraClass) { NSLog(@"Unable to get TestDylib class"); return; } /* *初始化方式采用下面的形式 alloc init的形式是行不通的 同樣,直接使用PacteraFramework類初始化也是不正確的 *通過- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2; 方法調用入口方法(bootLoader:WithBundle:),并傳遞參數(withObject:self withObject:frameworkBundle) */ NSObject *pacteraObject = [pacteraClass new]; [pacteraObject performSelector:@selector(bootLoader:WithBundle:) withObject:self withObject:frameworkBundle];
}</pre>
在這里推薦做一些后臺邏輯去驗證文件的完整和正確性。
也可以對生成的Framework進行加密壓縮處理。
綜上所述:這就可以實現動態的更新包替換,但是更推薦分模塊去加載,這樣做的好處不用多說,但是存在一定的技術難度和對整個項目的把控,同樣不要盲目的去實現,實現計算工程難度。
</div>
本文由用戶 gybddp 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!