ios app 实现热更新(无需发新版本实现app添加新功能)

目前能够实现热更新的方法,总结起来有以下三种

1. 使用FaceBook 的开源框架 reactive native,使用js写原生的iOS应用

ios app可以在运行时从服务器拉取最新的js文件到本地,然后执行,因为js是一门动态的

脚本语言,所以可以在运行时直接读取js文件执行,也因此能够实现ios的热更新

2. 使用lua 脚本。lua脚本如同js 一样,也能在动态时被。之前愤怒的小鸟使用

lua脚本做的一个插件 wax,可以实现使用lua写ios应用。热更新时,从服务器拉去lua脚本

然后动态的执行就可以了。遗憾的是 wax目前已经不更新了。

上面是网上现在能够搜到的热更新方法。

xcode 6 之后,苹果开放了 ios 的动态库编译权限。所谓的动态库,其实就是可以在运行时加载。

正好利用这一个特性,用来做ios的热更新。

1.

建立一个动态库,如图:

动态库包含需要使用的viewCOntroller,当然可以包含任何需要使用的自定义ui和逻辑。

动态库的入口是一个jkDylib的类。它的.h和.m文件分别如下:

[objc] view plain copy

  1. //
  2. //  JKDylib.h
  3. //  JKDylb
  4. //
  5. //  Created by wangdan on 15/7/5.
  6. //  Copyright (c) 2015年 wangdan. All rights reserved.
  7. //
  8. #import <Foundation/Foundation.h>
  9. @interface JKDylib : NSObject
  10. -(void)showViewAfterVC:(id)fromVc inBundle:(NSBundle*)bundle;
  11. @end

.m文件

[objc] view plain copy

  1. //
  2. //  JKDylib.m
  3. //  JKDylb
  4. //
  5. //  Created by wangdan on 15/7/5.
  6. //  Copyright (c) 2015年 wangdan. All rights reserved.
  7. //
  8. #import "JKDylib.h"
  9. #import "JKViewController.h"
  10. @implementation JKDylib
  11. -(void)showViewAfterVC:(id)fromVc inBundle:(NSBundle*)bundle
  12. {
  13. if (fromVc == nil ) {
  14. return;
  15. }
  16. JKViewController *vc = [[JKViewController alloc] init];
  17. UIViewController *preVc = (UIViewController *)fromVc;
  18. if (preVc.navigationController) {
  19. [preVc.navigationController pushViewController:vc animated:YES];
  20. }
  21. else {
  22. UINavigationController *navi = [[UINavigationController alloc] init];
  23. [navi pushViewController:vc animated:YES];
  24. }
  25. }
  26. @end

上述代码意图非常明显,

就是调用该动态库的时候

[objc] view plain copy

  1. -(void)showViewAfterVC:(id)fromVc inBundle:(NSBundle*)bundle

在该函数中,创建一个viewController 然后使用mainBundler 的navigationController  push 新建的viewController,显示动态库的ui界面。

而动态库中的JKViewController 内容则可以根据需要随便定义。

2. 完成上述动态库的编译工作后,现在需要做的就是在主工程中,写一段加载该动态库的代码。

主工程目录如下:

在最重要的viewCotrooler里面,定义了加载动态库的方法:

[objc] view plain copy

  1. //
  2. //  ViewController.m
  3. //  DylibTest
  4. //
  5. //  Created by wangdan on 15/7/5.
  6. //  Copyright (c) 2015年 wangdan. All rights reserved.
  7. //
  8. #import "ViewController.h"
  9. #import "AFNetWorking.h"
  10. @interface ViewController ()
  11. @end
  12. @implementation ViewController
  13. - (void)viewDidLoad {
  14. [super viewDidLoad];
  15. self.view.backgroundColor = [UIColor whiteColor];
  16. self.title = @"bundle test";
  17. AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] init];
  18. manager.responseSerializer = [AFJSONResponseSerializer serializer];
  19. NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]];
  20. [manager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
  21. NSLog(@"request success");
  22. } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
  23. NSLog(@"request failure");
  24. }];
  25. UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 100, 100, 50)];
  26. btn.backgroundColor = [UIColor blueColor];
  27. [btn addTarget:self
  28. action:@selector(btnHandler)
  29. forControlEvents:UIControlEventTouchUpInside];
  30. [self.view addSubview:btn];
  31. NSString *document = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
  32. BOOL writeResult =
  33. [@"hellow" writeToFile:[NSString stringWithFormat:@"%@/%@",document,@"hello.plist"] atomically:YES encoding:NSUTF8StringEncoding error:nil];
  34. // Do any additional setup after loading the view, typically from a nib.
  35. }
  36. -(void)btnHandler
  37. {
  38. //AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] init];
  39. //manager.responseSerializer = [AFJSONResponseSerializer serializer];
  40. // NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]];
  41. // [manager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
  42. //    NSLog(@"request success");
  43. // } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
  44. // NSLog(@"request failure");
  45. //}];
  46. NSString *documentDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
  47. NSString *bundlePath = [NSString stringWithFormat:@"%@/%@",documentDirectory,@"JKDylb.framework"];
  48. if (![[NSFileManager defaultManager] fileExistsAtPath:bundlePath]) {
  49. NSLog(@"file not exist ,now  return");
  50. return;
  51. }
  52. NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
  53. if (!bundle || ![bundle load]) {
  54. NSLog(@"bundle load error");
  55. }
  56. Class loadClass = [bundle principalClass];
  57. if (!loadClass) {
  58. NSLog(@"get bundle class fail");
  59. return;
  60. }
  61. NSObject *bundleObj = [loadClass new];
  62. [bundleObj performSelector:@selector(showViewAfterVC:inBundle:) withObject:self withObject:bundle];
  63. NSString *framePath = [[NSBundle mainBundle] privateFrameworksPath];
  64. NSLog(@"framePath is %@",framePath);
  65. NSLog(@"file attri \n %@",bundle.localizations);
  66. //    [bundleObj showViewAfterVC:self inBundle:bundle];
  67. }
  68. - (void)didReceiveMemoryWarning {
  69. [super didReceiveMemoryWarning];
  70. // Dispose of any resources that can be recreated.
  71. }
  72. @end

viewController视图中有一个按钮,点击按钮后,从 document目录下面找到动态库(虽然此时document下并没有动态库),动态库的名称约定好味

JKDylib.framework

然后使用NSBundle 加载该动态库,具体见代码。

加载成功后,调用在动态库中实现的方法

[objc] view plain copy

  1. [bundleObj performSelector:@selector(showViewAfterVC:inBundle:) withObject:self withObject:bundle];

编译该工程,然后运行到手机上,然后退出该程序

3. 打开itunes 然后将动态库同步到刚才的测试工程目录下。

4.在此打开测试工程程序,点击button,则会发现能够进入在动态库中定义的ui界面了。

上面工程的参考代码 在

http://download.csdn.net/detail/j_akill/8891881

关于动态更新的思考:

采用动态库方式实现热更新其实还是有一个问题,就是如何在主工程和动态库之间共享组建

比如网络组件以及其他等等第三方组件。

目前我没发现好方法,只能在动态库和主工程之间分别添加并且编译。

时间: 2024-10-05 05:41:35

ios app 实现热更新(无需发新版本实现app添加新功能)的相关文章

ios app 实现热更新(无需发新版本号实现app加入新功能)

眼下可以实现热更新的方法,总结起来有下面三种 1. 使用FaceBook 的开源框架 reactive native,使用js写原生的ios应用 ios app能够在执行时从server拉取最新的js文件到本地.然后执行,由于js是一门动态的 脚本语言.所以可以在执行时直接读取js文件执行,也因此可以实现ios的热更新 2. 使用lua 脚本.lua脚本如同js 一样,也能在动态时被.之前愤慨的小鸟使用 lua脚本做的一个插件 wax,能够实现使用lua写ios应用.热更新时,从server拉去

waxpatch实现上线app的热更新

为什么需要 WaxPatch 很多情况下,已经在 AppStore 上线的应用需要紧急缺陷修复,此时便需要使用某些技术手段,使应用程序能够动态下载补丁,进行缺陷修复. 什么是 WaxPatch 迄今为止,脚本语言中运行速度最快的是 Lua.Lua 语言由巴西里约热内卢天主教大学的 Roberto Ierusalimschy.Waldemar Celes 和 Luiz Henrique de Figueiredo 于 1993 年开发的.其最初的设计目的是提供一个方便嵌入到应用程序中得脚本语言.L

iOS热更新的几种方案

iOS APP的上架审核一直是个令人困扰的问题,动辄一个星期甚至半个月的审核时间,往往会耽误产品的运营计划. 尤其是,审核过程中难以避免的会被苹果拒绝,然后又是一个周期,很是痛苦. 除了在提交审核前,尽可能的保证产品没有Bug,以及充分研究苹果的app审核政策外,从技术开发层面如果能解决热更新问题,则再好不过了. 所以我简单整理了以下一些技术,可用于产品的内部更新,而不用重新提交给苹果审核.如果有更多的方案,或是错误,也请提出. 1. Hybrid App 混合架构,借助于Html,JS等前端技

React Native之code-push的热更新(ios android)

React Native之code-push的热更新(ios android) React Native支持大家用React Native技术开发APP,并打包生成一个APP.在动态更新方面React Native只是提供了动态更新的基础,对将应用部署到哪里,如何进行动态更新并没有支持的那么完善.好在微软开发了CodePush,填补React Native 应用在动态更新方面的空白.CodePush 是微软提供的一套用于热更新 React Native 和 Cordova 应用的服务.下面将向大

React-Native 告别CodePush,自建热更新版本升级环境

微软的CodePush热更新非常难用大家都知道,速度跟被墙了没什么区别. 另外一方面,我们不希望把代码放到别人的服务器.自己写接口更新总归感觉安全一点. so,就来自己搞个React-Native APP的热更新管理工具吧.暂且命名为hotdog. /**************************************************/ 首先我们要弄清react-native启动的原理,是直接调用jslocation的jsbundle文件和assets资源文件. 由此,我们可以自

Android Muitldex热更新修复方案原理

前言 做程序开发,基础很重要.同样是拧螺丝人家拧出来的可以经久不坏,你拧出来的遇到点风浪就开始颤抖,可见基本功的重要性.再复杂的技术,也是由一个一个简单的逻辑构成.先了解核心基础,才能更好理解前沿高新技术. 正文大纲 先看效果{github Demo地址}:(https://github.com/18598925736/HotUpdateDemo) Demo使用方法 Demo源码概览 热修复核心技术 基础知识预备 hook思路 TIPS 热更新技术,不是新话题.目前最热门的热更新由两种,一种是腾

苹果禁用热更新

原标题:苹果禁用热更新 可能也是无法容忍这些“灰色行为”了 转载地址:http://sd.china.com.cn/a/2017/keji_0313/892062.html 3月8日晚,一封来自苹果的邮件在国内APP开发者的群体中爆炸.该邮件的主要内容是:禁止在应用/游戏里面使用Lua或JavaScript脚本进行热更新(国内主要是使用rollout.jspatch的热更新技术框架).邮件一出,国内的程序员团体哀鸿遍野,甚至传闻有公司将有关运用jspatch技术的部门整个砍掉. 苹果向开发者发出

Android 腾讯Bugly 热更新

这个是一位大佬教我的,我自己照着做写博客 热更新虽然看起来很复杂,但是Bugly通过集成,使得这个过程很简单.我这里不涉及多渠道热更新,只讲述最简单的情况. 1.首先我们需要在Bugly上有个应用这个不就不多说,我的上一篇博客写了,大家可以去参考http://blog.csdn.net/z979451341/article/details/78696789 2.配置环境 工程根目录下"build.gradle"文件中添加: buildscript { repositories { jc

nodejs 热更新

gulp监控工具nodemon,可以监视代码的改动而重启服务器,然而还是觉得若不用重启而直接加载新的代码更方便,所以在网上找了下nodejs热更新的方法,顺便记录一下 其实,方法也是通过监视文件被改动的时候,将缓冲区中已加载的对应模块清除,此时缓冲区中就不保留有该文件模块的代码,直至下一个请求该文件模块到来时,才会去重新加载一遍对应的模块,而正是改动之后的文件模块. 而总结出来要解决的问题有如下三个: 如何更新模块代码 如何使用新模块处理请求 如何释放老模块的资源 先看看node相关的源代码: