iOS Runtime 實(shí)踐(1)

iOS Runtime

很多時(shí)候我們都在看iOS開發(fā)中的黑魔法——Runtime跪楞。懂很多闪金,但如何實(shí)踐卻少有人提及。本文便是iOS Runtime的實(shí)踐第一篇菇爪。

WebView

我們這次的實(shí)踐主題唠梨,是使用針對接口編程的方式袋励,借助Excalibur系統(tǒng),來達(dá)到動(dòng)態(tài)切換UIWebViewWKWebkit的目的当叭。
??為什么要?jiǎng)討B(tài)切換茬故?其實(shí)我們眾所周知,Apple的UIWebView存在巨大的內(nèi)存泄漏蚁鳖。當(dāng)網(wǎng)頁內(nèi)容較復(fù)雜磺芭,圖片較大時(shí),經(jīng)常會(huì)出現(xiàn)150MB+的內(nèi)存占用率醉箕;并且這個(gè)內(nèi)存占用率會(huì)一直存在無法消除钾腺。雖然StackOverflow上有很多大神想出了各種方式,但作用卻很小讥裤。
??Apple 從 iOS8 開始垮庐,推出了更新、優(yōu)化更好的WKWebkit坞琴。這個(gè)庫是UIWebView的繼承者,在相同的瀏覽頁面下逗抑,WKWebKit提供的WKWebView的內(nèi)存占用率甚至可以只有UIWebView1/10剧辐。可惜的是邮府,我們很多時(shí)候?yàn)榱吮WC用戶的覆蓋率荧关,target iOS Version都是 iOS7。這時(shí)候我們就需要使用UIWebView來達(dá)到顯示的目的褂傀。
那么問題來了忍啤,如何實(shí)現(xiàn)根據(jù)iOS版本來達(dá)到動(dòng)態(tài)加載的目的呢?

Excalibur

Excalibur是我們用來映射和字符串scheme對應(yīng)關(guān)系的類。通過注冊scheme對應(yīng)的類同波,來達(dá)到目的鳄梅。
??注冊一個(gè)類:

+ (void)registerScheme:(nonnull NSString *)scheme
              forClass:(nonnull __unsafe_unretained Class)aClass {
    NSParameterAssert(scheme);
    NSParameterAssert(aClass);
    if ([Excalibur classForScheme:scheme]) {
        [NSException raise:@"Scheme Already Exists"
                    format:@"'%@' Scheme Already Exists", scheme];
        return;
    }
    if (![aClass isSubclassOfClass:[NSObject class]]) {
        [NSException raise:@"Wrong Class Type"
                    format:@"Class should inherit from NSObject"];
        return;
    }
    if ([scheme isEqualToString:@""]) {
        [NSException raise:@"Scheme Wrong"
                    format:@"Scheme should not be blank"];
        return;
    }
    [sharedInstance addScheme:scheme forClass:aClass];
}

Excalibur中獲取scheme指定的

+ (nullable __unsafe_unretained Class)classForScheme:(nonnull NSString *)scheme {
    return [sharedInstance.mapTable objectForKey:scheme];
}

通過Excalibur,我們使用哪個(gè)未檩,就可以在Runtime時(shí)期才確定戴尸。

針對接口編程

在設(shè)計(jì)模式上,我們經(jīng)常聽到說冤狡,要針對接口編程孙蒙。那么在iOS開發(fā)中,怎樣才算是針對接口編程呢悲雳?這個(gè)又有什么好處呢挎峦?
??在Objective-C語言中,我們一般認(rèn)為Protocol便是接口功能的協(xié)議合瓢。
??這里坦胶,我們想達(dá)到的目的,是在不同的iOS版本下歪玲,調(diào)用不同的Webkit來進(jìn)行網(wǎng)頁渲染迁央。而網(wǎng)頁的渲染一般放在一個(gè)ViewController下,因此我們可以針對這個(gè)需求滥崩,制訂一個(gè)用來渲染指定URLViewController接口:

@protocol DWKProtocol <NSObject>

+ (instancetype)webViewControllerForUrl:(NSURL *)url;

@end

這里的接口岖圈,返回一個(gè)ViewController,該VC可以用來打開url網(wǎng)頁钙皮。
??現(xiàn)在我們可以寫兩個(gè)ViewController蜂科,分別是DWKWebViewControllerDWKWebkitViewController;其中DWKWebViewController使用UIWebView來渲染網(wǎng)頁:

@interface DWKWebViewController ()

@property (nonatomic, strong) UIWebView *webView;
@property (nonatomic, strong) NSURL *url;

@end

DWKWebkitViewController則使用WKWebView來渲染網(wǎng)頁:

@interface DWKWebkitViewController ()

@property (nonatomic, strong) WKWebView *webView;
@property (nonatomic, strong) NSURL *url;

@end

接下來短条,二者在Runtime的初始化階段向Excalibur注冊自己:

DWKWebViewController
+ (void)load {
    if (iOSVersion < 8.0) {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            [Excalibur registerScheme:DWK_MODULE_WEB_VC forClass:[self class]];
        });
    }
}
DWKWebkitViewController
+ (void)load {
    if (iOSVersion >= 8.0) {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            [Excalibur registerScheme:DWK_MODULE_WEB_VC forClass:[self class]];
        });
    }
}

那么导匣,8.0以下時(shí),DWKWebViewController就會(huì)是DWK_MODULE_WEB_VC模塊的實(shí)現(xiàn)者茸时;而在8.0及其以上時(shí)贡定,DWKWebkitViewController則是DWK_MODULE_WEB_VC模塊的實(shí)現(xiàn)者。

調(diào)用

做好了以上兩步準(zhǔn)備可都,接下來便是調(diào)用DWK_MODULE_WEB_VC的模塊來渲染網(wǎng)頁了缓待。
這里,我們已經(jīng)約定好渠牲,實(shí)現(xiàn)DWK_MODULE_WEB_VCViewController肯定會(huì)實(shí)現(xiàn)DWKProtocol旋炒,因此我們可以這樣來獲取我們想要的ViewController Class

Class <DWKProtocol> webViewControllerClass = [Excalibur classForScheme:DWK_MODULE_WEB_VC];
UIViewController<DWKProtocol> *webViewController = [webViewControllerClass webViewControllerForUrl:[NSURL URLWithString:@"www.baidu.com"]];

總結(jié)

至此,使用Runtime達(dá)到動(dòng)態(tài)加載UIWebViewWKWebkit的目的達(dá)成签杈。

代碼鏈接

我把代碼放到了Github上瘫镇,希望對你有所幫助:

https://github.com/DemoMania/dynamicWebkit

如果有問題,還請留言。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末铣除,一起剝皮案震驚了整個(gè)濱河市谚咬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌通孽,老刑警劉巖序宦,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異背苦,居然都是意外死亡互捌,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門行剂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來秕噪,“玉大人,你說我怎么就攤上這事厚宰‰缃恚” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵铲觉,是天一觀的道長澈蝙。 經(jīng)常有香客問我,道長撵幽,這世上最難降的妖魔是什么灯荧? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮盐杂,結(jié)果婚禮上逗载,老公的妹妹穿的比我還像新娘。我一直安慰自己链烈,他們只是感情好厉斟,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著强衡,像睡著了一般擦秽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上漩勤,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天号涯,我揣著相機(jī)與錄音,去河邊找鬼锯七。 笑死,一個(gè)胖子當(dāng)著我的面吹牛誉己,可吹牛的內(nèi)容都是我干的眉尸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼噪猾!你這毒婦竟也來了霉祸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤袱蜡,失蹤者是張志新(化名)和其女友劉穎丝蹭,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坪蚁,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡奔穿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了敏晤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贱田。...
    茶點(diǎn)故事閱讀 40,505評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖嘴脾,靈堂內(nèi)的尸體忽然破棺而出男摧,到底是詐尸還是另有隱情,我是刑警寧澤译打,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布耗拓,位于F島的核電站,受9級特大地震影響奏司,放射性物質(zhì)發(fā)生泄漏乔询。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一结澄、第九天 我趴在偏房一處隱蔽的房頂上張望哥谷。 院中可真熱鬧,春花似錦麻献、人聲如沸们妥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽监婶。三九已至,卻和暖如春齿桃,著一層夾襖步出監(jiān)牢的瞬間惑惶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工短纵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留带污,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓香到,卻偏偏與公主長得像鱼冀,于是被迫代替她去往敵國和親报破。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評論 2 359

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