您的位置:首页 > 移动开发 > IOS开发

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

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



 

 
第二步:生成的工程中原本的类删掉不用
 
然后添加新的类文件来实现动态加载效果



 

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

[objc] view plaincopy




 

/* 

 主程序和此动态库的关系枢纽,也就是从“主程序”到“动态库内封装的程序”的入口方法 

 @param mainCon “主程序”中入口按钮所在的ViewController对象 

 @param bundle 此动态库在document文件中的路径,用于xib的加载和图片的加载 

 */  

-(void)showView:(id)mainCon withBundle:(NSBundle *)bundle;  

实现此方法:

 
 

[objc] view plaincopy




 

-(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基类的代码做说明)

 
 

[objc] view plaincopy




 

/* 

     *注意获取图片的方式,通过路径+图片名称去获取 

     *如果直接使用[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,并调用上面提到的动态库入口方法和传递参数
(此项目在界面上添加了一个简单的按钮,点击按钮来进入动态库)
 

[objc] view plaincopy




 

-(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下载地址:点击跳转到下载页面 

感谢:http://blog.csdn.net/like7xiaoben/article/details/44081257

 





大小: 114.5 KB

动态模块更新__1_.zip (358.8 KB)

下载次数: 2





大小: 61.3 KB





大小: 95 KB





大小: 35.2 KB





大小: 120.7 KB





大小: 96.5 KB





大小: 159.2 KB

查看图片附件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: