iOS Runtime 实践(1)
很多时候我们都在看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)的更多相关文章
- 包建强的培训课程(11):iOS Runtime实战
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- iOS runtime探究(二): 从runtime開始深入理解OC消息转发机制
你要知道的runtime都在这里 转载请注明出处 http://blog.csdn.net/u014205968/article/details/67639289 本文主要解说runtime相关知识, ...
- ios runtime swizzle
ios runtime swizzle @implementation NSObject(Extension) + (void)swizzleClassMethod:(Class)class orig ...
- ios runtime的相关知识
一.iOS runtime原理 对于runtime机制,在网上找到的资料大概就是怎么去用这些东西,以及查看runtime.h头文件中的实现,当然这确实是一种很好的学习方法,但是,其实我们还是不会知道r ...
- CI Weekly #18 | flow.ci iOS 最佳实践出炉,正式支持 Git@OSC 构建
如大家所期待,flow.ci 现已支持开源中国的代码仓库 - 码云,可以直接构建 Git@OSC 的项目了,点击创建项目-选择代码仓库-选择码云-绑定 OSChina 账户-选择要构建项目,教程看这里 ...
- iOS Runtime的消息转发机制
前面我们已经讲解Runtime的基本概念和基本使用,如果大家对Runtime机制不是很了解,可以先看一下以前的博客,会对理解这篇博客有所帮助!!! Runtime基本概念:https://www.cn ...
- iOS Runtime 实操练习
iOS Runtime 知识详解: http://yulingtianxia.com/blog/2014/11/05/objective-c-runtime/ 一般可以运行Runtime进行以下操作 ...
- IOS runtime动态运行时二
在C#.Java中有编译时多态和运行时多态,在OC中,只有运行时的多态,这与它的运行机制有关.OC中,方法的调用是通过消息的传递来进行的.在IOS runtime动态运行时一http://www.cn ...
- iOS 开发实践之 Auto Layout
原:http://xuexuefeng.com/autolayout/?utm_source=tuicool 本文是博主 iOS 开发实践系列中的一篇,主要讲述 iOS 中 Auto Layout(自 ...
随机推荐
- python学习之”迭代从入门到精通“
在开发的过程中,假如给你一个list或者tuple,我们可以通过for循环来遍历这个list或者tuple,这种遍历我们成为迭代(Iteration).在Python中,迭代是通过for ... in ...
- 今天,安装了一个GANGLIA玩玩,以后再测试NAGIOS吧。
说不定以后派得上用场呢.. 还有,NGINX也要学,不能老是凭站IIS,APACHE混饭吃吧,现在它都这么流行了..新浪,网易,腾讯.
- Android开源项目发现---ActionBar篇(持续更新)
1. ActionBarSherlock 鼎鼎大名, 为Android所有版本提供统一的ActionBar,解决4.0以下ActionBar的适配问题 项目地址:https://github.com/ ...
- Android用户界面 UI组件--TextView及其子类(四) Chronometer计时器
Chronometer是一个简单的定时器,你可以给它一个开始时间,并以此定时,或者如果你不给它一个开始时间,它将会使用你的时间通话开始.默认情况下它会显示在当前定时器的值的形式“分:秒”或“H:MM: ...
- oracle稳定执行计划1
稳定执行计划 1 策略: Oracle的sql 执行计划在一些场景下会发生变化,导致系统会发生不可知的情况,影响系统的稳定性,特别是关键业务的sql. 比如下面的场景: 统计信息过老,重新收集了统计信 ...
- ArrayList集合排序
using System;using System.Collections;using System.Collections.Generic;using System.Text; namespace ...
- 如何在多线程中调用winform窗体控件
由于 Windows 窗体控件本质上不是线程安全的.因此如果有两个或多个线程适度操作某一控件的状态(set value),则可能会迫使该控件进入一种不一致的状态.还可能出现其他与线程相关的 bug,包 ...
- easyui-lang-zh_CN.js导入后还是英文提示
<script src="/js/easyUI1.3.3/jquery.easyui.min.js" type="text/javascript"> ...
- linux中替换目录下的某个文件中包含的IP地址
#!/bin/bash #set -x oldIP=172.17.39.135 newIP=172.17.98.115 homefile=/usr/local/ims/ filelist=`grep ...
- JavaScript---网络编程(11)--DHTML技术演示(4)-单选框/下拉菜单/添加文件
本节讲述单选框/下拉菜单/添加文件,综合css,html和JavaScript. 单选框: 实现的功能是:(类似平时的性格测试) 先隐藏一部分页面,然后通过点击单选框来显示. 再通过选项的选择-(每个 ...