很多时候我们都在看iOS开发中的黑魔法——Runtime。懂很多,但如何实践却少有人提及。本文便是iOS Runtime的实践第一篇。

WebView

我们这次的实践主题,是使用针对接口编程的方式,借助Excalibur系统,来达到动态切换UIWebView和WKWebkit的目的。

为什么要动态切换?其实我们众所周知,Apple的UIWebView存在巨大的内存泄漏。当网页内容较复杂,图片较大时,经常会出现150MB+的内存占用率;并且这个内存占用率会一直存在无法消除。虽然StackOverflow上有很多大神想出了各种方式,但作用却很小。

Apple 从 iOS8 开始,推出了更新、优化更好的WKWebkit。这个库是UIWebView的继承者,在相同的浏览页面下,WKWebKit提供的WKWebView的内存占用率甚至可以只有UIWebView的1/10。可惜的是,我们很多时候为了保证用户的覆盖率,target iOS Version都是 iOS7。这时候我们就需要使用UIWebView来达到显示的目的。

那么问题来了,如何实现根据iOS版本来达到动态加载的目的呢?

Excalibur

Excalibur是我们用来映射类和字符串scheme对应关系的类。通过注册scheme对应的类,来达到目的。

注册一个类:

+ (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,我们使用哪个类,就可以在Runtime时期才确定。

针对接口编程

在设计模式上,我们经常听到说,要针对接口编程。那么在iOS开发中,怎样才算是针对接口编程呢?这个又有什么好处呢?

在Objective-C语言中,我们一般认为Protocol便是接口功能的协议。

这里,我们想达到的目的,是在不同的iOS版本下,调用不同的Webkit来进行网页渲染。而网页的渲染一般放在一个ViewController下,因此我们可以针对这个需求,制订一个用来渲染指定URL的ViewController接口:

@protocol DWKProtocol

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

@end

这里的接口,返回一个ViewController,该VC可以用来打开url网页。

现在我们可以写两个ViewController,分别是DWKWebViewController和DWKWebkitViewController;其中DWKWebViewController使用UIWebView来渲染网页:

@interface DWKWebViewController ()

@property (nonatomic, strong) UIWebView *webView;

@property (nonatomic, strong) NSURL *url;

@end

而 DWKWebkitViewController则使用WKWebView来渲染网页:

@interface DWKWebkitViewController ()

@property (nonatomic, strong) WKWebView *webView;

@property (nonatomic, strong) NSURL *url;

@end

接下来,二者在Runtime的初始化阶段向Excalibur注册自己:

DWKWebViewController

+ (void)load {

if (iOSVersion

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以下时,DWKWebViewController就会是DWK_MODULE_WEB_VC模块的实现者;而在8.0及其以上时,DWKWebkitViewController则是DWK_MODULE_WEB_VC模块的实现者。

调用

做好了以上两步准备,接下来便是调用DWK_MODULE_WEB_VC的模块来渲染网页了。

这里,我们已经约定好,实现DWK_MODULE_WEB_VC的ViewController肯定会实现DWKProtocol,因此我们可以这样来获取我们想要的ViewController Class:

Class  webViewControllerClass = [Excalibur classForScheme:DWK_MODULE_WEB_VC];

UIViewController *webViewController = [webViewControllerClass webViewControllerForUrl:[NSURL URLWithString:@"www.baidu.com"]];

总结

至此,使用Runtime达到动态加载UIWebView和WKWebkit的目的达成。

代码链接

我把代码放到了Github上,希望对你有所帮助:

https://github.com/DemoMania/dynamicWebkit

iOS Runtime 实践(1)的更多相关文章

  1. 包建强的培训课程(11):iOS Runtime实战

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

  2. iOS runtime探究(二): 从runtime開始深入理解OC消息转发机制

    你要知道的runtime都在这里 转载请注明出处 http://blog.csdn.net/u014205968/article/details/67639289 本文主要解说runtime相关知识, ...

  3. ios runtime swizzle

    ios runtime swizzle @implementation NSObject(Extension) + (void)swizzleClassMethod:(Class)class orig ...

  4. ios runtime的相关知识

    一.iOS runtime原理 对于runtime机制,在网上找到的资料大概就是怎么去用这些东西,以及查看runtime.h头文件中的实现,当然这确实是一种很好的学习方法,但是,其实我们还是不会知道r ...

  5. CI Weekly #18 | flow.ci iOS 最佳实践出炉,正式支持 Git@OSC 构建

    如大家所期待,flow.ci 现已支持开源中国的代码仓库 - 码云,可以直接构建 Git@OSC 的项目了,点击创建项目-选择代码仓库-选择码云-绑定 OSChina 账户-选择要构建项目,教程看这里 ...

  6. iOS Runtime的消息转发机制

    前面我们已经讲解Runtime的基本概念和基本使用,如果大家对Runtime机制不是很了解,可以先看一下以前的博客,会对理解这篇博客有所帮助!!! Runtime基本概念:https://www.cn ...

  7. iOS Runtime 实操练习

    iOS  Runtime 知识详解: http://yulingtianxia.com/blog/2014/11/05/objective-c-runtime/ 一般可以运行Runtime进行以下操作 ...

  8. IOS runtime动态运行时二

    在C#.Java中有编译时多态和运行时多态,在OC中,只有运行时的多态,这与它的运行机制有关.OC中,方法的调用是通过消息的传递来进行的.在IOS runtime动态运行时一http://www.cn ...

  9. iOS 开发实践之 Auto Layout

    原:http://xuexuefeng.com/autolayout/?utm_source=tuicool 本文是博主 iOS 开发实践系列中的一篇,主要讲述 iOS 中 Auto Layout(自 ...

随机推荐

  1. bzoj 3144: [Hnoi2013]切糕 最小割

    3144: [Hnoi2013]切糕 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 681  Solved: 375[Submit][Status] ...

  2. hdu 4762 && 2013 ACM/ICPC 长春网络赛解题报告

    这次的答案是猜出来的,如果做得话应该是应该是一个几何概型的数学题: 答案就是:n/(m^(n-1)); 具体的证明过程: 1.首先枚举这M个点中的的两个端点,概率是:n*(n-1); 2.假设这个蛋糕 ...

  3. 【BZOJ1901】 Zju2112 Dynamic Rankings(树套树)

    [题意] 给定一个含有n个数的序列a[1],a[2],a[3]--a[n], 程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]--a[j]中第k小的数是多少(1≤k ...

  4. Android 性能优化 四 布局优化merge标签的使用

    小白:之前分享了ViewStub标签的使用,Android还有其他优化布局的方式吗? 小黑:<merge />标签用于减少View树的层次来优化Android的布局.先来用个例子演示一下: ...

  5. StorSimple 简介

     2014年 10月 28日,星期二 PRACHEETI NAGARKAR DESAI 混合云存储业务资深项目经理 在此我很荣幸地宣布StorSimple解决方案已经在中国正式上市.该方案为IT部 ...

  6. (转载)struct 与typdef struct的区别

    (转载)http://blog.csdn.net/piratejk/article/details/3491226 1. 基本解释 typedef为C语言的关键字,作用是为一种数据类型定义一个新名字. ...

  7. Toad for Oracle 使用文档

    Toad®for Oracle 版本 12.0.1 发行说明 30 July 2013 目录 欢迎使用 Toad for Oracle 版本更新 解决的问题和改进 已知问题 第三方已知问题 升级和兼容 ...

  8. selenium-webdriver的等待方法

    Wait commands in WebDriver Listing out the different WebDriver Wait statements that can be useful fo ...

  9. linux修改主机名

    查看机器名:uname -a 修改机器名: redhat中修改主机名 第一步:#hostname oratest 第二步:修改/etc/sysconfig/network中的hostname 第三步: ...

  10. [NOIP2007]奖学金

      题目来源:http://www.luogu.org/problem/show?pid=1093# 2007年NOIP全国联赛普及组 [题目描述 Description] 某小学最近得到了一笔赞助, ...