IOS-使用framework实现功能模块动态更新

测试Xcode版本为6.1.1

实现过程简述:把想要的作为动态更新的模块,移动到我们创建的Framework工程中,然后得到我们想要的动态库文件,把此文件再通过iTunes放到“主程序”项目的document文件夹下,从而实现从主程序中去加载此动态库,从而实现功能模块的动态更新效果。理想效果为支付宝APP,而支付宝采用的是HTML5(网页)的形式实现的,这是目前最通用的实现方式,但是不适用于复杂界面效果。

第一步:创建IOS Framework工程

第二步:生成的工程中原本的类删掉不用

然后添加新的类文件来实现动态加载效果

图片和测试界面不多说,重点为PacteraFramework这个类文件中的代码部分:

添加入口方法:

/*
 主程序和此动态库的关系枢纽,也就是从“主程序”到“动态库内封装的程序”的入口方法
 @param mainCon “主程序”中入口按钮所在的ViewController对象
 @param bundle 此动态库在document文件中的路径,用于xib的加载和图片的加载
 */
-(void)showView:(id)mainCon withBundle:(NSBundle *)bundle;

实现此方法:

-(void)showView:(id)mainCon withBundle:(NSBundle *)bundle
{
    /*
     *初始化第一个controller
      TheFirstViewController继承于RootViewController
     *这里的重点是xib文件的加载
      通常我们在初始化xib的时候并不是很在意bundle:这个参数,一般情况下都会赋予nil值
      其实我们所用到的图片、xib等资源文件都是在程序内部中获取的,也就是我们常用的[NSBundle mainBundle]中获取,所谓的NSBundle本质上就是一个路径,mainBundle指向的是.app下。
      而如果我们不指定bundle,则会默认从.app路径下去寻找资源。
      不过很显然,我们的动态库是放到“主程序”的document文件下的,所以资源文件是不可能在[NSbundle mainBundle]中获取到的,所以这里我们需要指定bundle参数,这也是传递framework的路径的意义所在
     */
    TheFirstViewController *firstCon = [[TheFirstViewController alloc]initWithNibName:@"TheFirstViewController" bundle:bundle];
    //保存NSBundle
    firstCon.root_bundle = bundle;

    //加上导航栏,并隐藏。
    UINavigationController *navCon = [[UINavigationController alloc]initWithRootViewController:firstCon];
    [navCon setNavigationBarHidden:YES];

    //转换传递过来的mainCon参数,实现界面跳转
    UIViewController *viewCon = (UIViewController *)mainCon;
    [viewCon presentViewController:navCon animated:YES completion:^{
        NSLog(@"跳转到动态更新模块成功!");
    }];
}

上面描述了xib文件的加载,下面是使用图片的注意事项:(使用RootViewController基类的代码做说明)

/*
     *注意获取图片的方式,通过路径+图片名称去获取
     *如果直接使用[UIImage imageNamed:@"root_top_bg.png"]方式加载是会出现问题,
      因为在当前程序的路径下是找不到此图片的,图片也会被封装到framwork中
     *如果在xib文件中直接为某个控件添加图片的话,和平常使用一样直接添加图片名称,不会出现路径的问题
     */
    [navImageView setImage:[UIImage imageWithContentsOfFile:[self.root_bundle pathForResource:@"root_top_bg" ofType:@"png"]]];

以上为一些frameweok工程中的注意事项,现在我们运行得到动态库文件

选择Show in Finder,取出framwork文件

第三步:创建“主程序”的项目工程

第四步:设置此工程可以通过iTunes来实现文件共享

然后通过itunes把framework放到document路径中

第五步:获取framework,并调用上面提到的动态库入口方法和传递参数

(此项目在界面上添加了一个简单的按钮,点击按钮来进入动态库)

-(void)testFramework
{
    NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
    NSString *documentDirectory = nil;
    if ([paths count] != 0)
        documentDirectory = [paths objectAtIndex:0];

    //拼接我们放到document中的framework路径
    NSString *libName = @"PacteraFramework.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;

    //加载方式一:使用dlopen加载动态库的形式 使用此种方法的时候注意头文件的引入
//    void* lib_handle = dlopen([destLibPath cStringUsingEncoding:NSUTF8StringEncoding], RTLD_LOCAL);
//    if (!lib_handle) {
//        NSLog(@"Unable to open library: %s\n", dlerror());
//        return;
//    }
    //加载方式一 关闭的方法
    // Close the library.
//    if (dlclose(lib_handle) != 0) {
//        NSLog(@"Unable to close library: %s\n",dlerror());
//    }

    //加载方式二:使用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(@"PacteraFramework");
    if (!pacteraClass) {
        NSLog(@"Unable to get TestDylib class");
        return;
    }

    /*
     *初始化方式采用下面的形式
      alloc init的形式是行不通的
      同样,直接使用PacteraFramework类初始化也是不正确的
     *通过- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
      方法调用入口方法(showView:withBundle:),并传递参数(withObject:self withObject:frameworkBundle)
     */
    NSObject *pacteraObject = [pacteraClass new];
    [pacteraObject performSelector:@selector(showView:withBundle:) withObject:self withObject:frameworkBundle];

}

第六步:运行“主程序”项目到设备上,然后点击按钮进入动态库模块吧。

注意:有时候我们运行framework工程获取framework文件,内部并没有我们想要的xib文件(这个时候内部展示的为nib格式的),所以在我们每次运行此工程的时候,都需要clean

demo下载地址:点击跳转到下载页面

时间: 2024-10-27 17:29:19

IOS-使用framework实现功能模块动态更新的相关文章

iOS 程序插件及功能动态更新思路

所用框架及语言 iOS客户端-Wax(开发愤怒的小鸟的连接Lua 和 Objc的框架),Lua,Objc, 服务端-Java(用于返回插件页面) 工具框架链接地址:Wax - https://github.com/probablycorey/wax  Netty - https://netty.io/  用做Http服务器,返回页面 由于Lua脚本语言,不需要编译即可运行,这点是我的这个思路可以执行的大前提,再加上苹果允许像Lua这样的脚本的存在,这一思路才能得以实现.个人感觉这一思路有点类似于

JSPatch – 动态更新iOS APP

博文转载至 http://blog.cnbang.net/works/2767/ JSPatch是最近业余做的项目,只需在项目中引入极小的引擎,就可以使用JavaScript调用任何Objective-C的原生接口,获得脚本语言的能力:动态更新APP,替换项目原生代码修复bug. 用途 是否有过这样的经历:新版本上线后发现有个严重的bug,可能会导致crash率激增,可能会使网络请求无法发出,这时能做的只是赶紧修复bug然后提交等待漫长的AppStore审核,再盼望用户快点升级,付出巨大的人力和

iOS-OC-APP热更新,动态更新(仿QQ打开或关闭某个功能)

一.前言 iOS开发更新APP我觉得是比较坑的就是审核时间比较长,审核比较严,对于刚入行的小伙伴来说,雷区比较多:所以热更新是比较重要的: 大家也许会发现我们常用的QQ现在下来也就一百多兆,但是用了几个月后发现QQ在手机上占有一个多G的内存,特别是手机内存比较小的小伙伴,这是因为你在使用过程中,有一些功能是你下载下来的: 二.创建Framework 1.新建项目 新建一个Cocoa Touch Framework项目,然后在这个项目里面写你的新的功能,比如我创建了一个控制器,在控制器里面加载一张

iOS 动态更新

iOS 动态更新 App 动态更新 1.控件到 window 的层级关系: 2.分析控件的详细路径: 3.动态修改控件: 4.工具篇: 视图的层级关系: 每个 App , 至少有一个根 Window , 通常情况下我们只用一个 .window 有一个 rootViewController , 这就是我们所谓的根视图 , 我们所有的控制器都是放在 rootViewController 里面的. 这个是最简单的层级关系 如果在项目里有了这么一个路径 , 我们可以做什么呢? 在当项目很复杂 , 可以其

如何通过反射实现动态功能模块加载

程序集包含模块,而模块包含类型,类型又包含成员.反射则提供了封装程序集.模块和类型的对象.您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型.然后,可以调用类型的方法或访问其字段和属性. 下面我们将介绍如何通过不使用反射的方式和使用反射的方式加载功能模块.实现效果: 1.        WinForm 主程序 主程序我们使用Winform程序,VS2008 工具C#语言开发.包括工具栏.状态栏及TabControl控件.我们使用TabControl 作为功能模块容器

[转] 通过反射实现动态功能模块加载

原文 如何通过反射实现动态功能模块加载 程序集包含模块,而模块包含类型,类型又包含成员.反射则提供了封装程序集.模块和类型的对象.您可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型.然后,可以调用类型的方法或访问其字段和属性. 下面我们将介绍如何通过不使用反射的方式和使用反射的方式加载功能模块.实现效果: 1. WinForm 主程序 主程序我们使用Winform程序,VS2008 工具C#语言开发.包括工具栏.状态栏及TabControl控件.我们使用TabCon

JS动态更新HTML5 APP页面的结构(包括功能和布局)

HTML5 APP开发算是越来越流程了.当然,开发这样的HTML5 APP有什么好处呢.笔者认为:可以通过后台JS动态更新HTML5 APP页面的结构,是一大优势. 那如何实现该功能呢. 首先,得知道其原理:为什么可以通过后台JS就可以更新前台APP. 接着,得知道操作步骤是怎样的. 详细内容,可以查看如下链接: HTML5 APP 实现后台JS更新APP前端页面功能 HTML5 APP开发之动态调整页面布局 如需要源码,请@我 (一份完整的源代码,收费1元)

iOS视频功能模块的开发

iOS视频功能模块的开发 一.使用MPMoviePlayerController进行视频播放 MPMoviePlayerController是iOS中进行视频播放开发的一个控制类,里面涵盖了视频播放中大部分的需求功能,在使用这个框架时,需要导入头文件<MediaPlayer/MediaPlayer.h>. 1.初始化方法 MPMoviePlayerController可以播放网络视频,也可以播放本地视频,通过不同的URL来进行初始化,例如本地视频的初始化如下: //视频文件路径     NSS

antd Select进阶功能 动态更新、函数防抖

一.动态更新Options Antd Select自带的搜索功能很多时候需要结合后端的接口,输入一个关键字的时候会自动更新选择器的选项. 下面列一些注意点 基础实现 选择器选项必须和每次更新的数据挂钩, 这个值可以通过state,也可以通过props拿到 再结合循环的方法例如map遍历渲染options import React, { PureComponent, Fragment } from 'react' import { Select } from 'antd' import axios