美文网首页iOS开发
workspace管理静态库和多个项目, 及cocoaPods的

workspace管理静态库和多个项目, 及cocoaPods的

作者: 大猿媛 | 来源:发表于2018-11-14 16:14 被阅读67次

    项目背景

    项目需求:
    在已有项目A的前提下,抽离出一个和项目A有公共业务甚至模块的项目B,对于公共业务和模块当然是想维护一份代码实现两个项目同步;差异性在于两个项目的主题风格、项目模块架构不一致,有各自独立的业务和功能。
    开发思路:
    1、copy出另一个target实现项目B的业务模块;否定原因:两个项目的UI、架构不一致,在didFinishlaunch时就有差异,这种需要通过判断当前target的方式进行差异性开发,代码会比较杂乱和难以维护,图片等资源文件的分离使用也很难做到,另外还会增大开发包的体积
    2、组件化开发;将公共基础模块和业务模块完全独立,使用pod管理不同组件,两个独立项目中进行各自的引用;否定原因:1)开发时间紧迫,人手不足,完全抽离组件不太理想 ,2)对于公共业务模块,两个项目的风格也不尽相同,某种程度上不能完全独立,3)现状是公共的业务模块也需要开发升级,抽离出去就需要不停维护,这种不稳定状态实际上不适合封装成组件
    3、workspace工作区开发;采纳原因:1)不同于组件抽离,workspace内的静态库可以灵活抽取,不用像组件那样需要完全和外部解耦,可以把工具,三方库,category等自定义的和项目AB公共的业务模块都放在静态库, 2)由于静态库被项目引用后,图片资源通过bundle管理并且内置于项目,所以图片资源可以独立两份于两个项目中,3)公共业务只需在静态库中进行开发,两个项目引用静态库就好,静态库把外部使用的类的头文件设置好就可以了;
    4、具体开发过程和遇到的问题,就往下看吧

    项目配置

    实际开发项目:一个workspace中一个静态库和两个项目

    一、创建workspace工作区,cocoaTouch static library,projectA 和 projectB
    1.1 workspace文件,不多说,直接上图,创建好后只会生成一个.xcworkspace文件,无其他文件生成 选择创建workspace
    1.2 创建静态库,由于苹果不支持开发者使用动态库,所以我们使用静态库(当然也可以选择动态库CocoaTouch Framework再改成静态库,还是有不同的) 选择创建静态库
    静态库最后一步 静态库创建的时候最好和workspace文件在同一目录下,便于管理
    1.3 两个项目的创建和日常创建项目无异,只是要和静态库一样,选择addTo和group到刚刚创建的workspace 最终的文件目录, 如图,两个项目一个静态库在一个workspace下 workspace文件目录
    二、静态库的配置和项目中的使用

    1、由于我们是在workspace中创建静态库,和独立的静态库使用不同(将.a文件拖拽入项目即可),而是在同一个workspace里,一起编译,具体往下看

    1.1 前往静态库的target的Build phases,添加copy Files,以便项目中引用静态库暴露的头文件

    如何将静态库中的类暴露出去

    1.2 项目引用.a静态库,Link binary with libraries下,add
    libCommonLibrary.a
    1.3 访问静态库的类,#import<CommonLibrary/CommonLibrary.h>
    至此,项目中如何应用静态库和访问其类就结束了,心好累吧

    静态库中xib和图片资源的管理

    先解释一下这个过程,在项目A中引入.a静态库,对于[NSBundle mainBundle]返回的是项目A的bundle,那么.a中的xib和图片资源肯定是不在项目A的bundle中的,所以在.a中如何加载xib和图片呢,下面要讲,如何管理静态库中的资源文件

    • 关于Bundle

    对于bundle可以理解为一个捆绑包,个人理解bundle为一个独立的空间,而我们的可执行(executable)工程,打包完之后,也是一个捆绑包,我们称之为主bundle,这个主bundle包含了可执行代码,如各个viewcontroller的可执行代码,和相关资源例如图片资源等。

    使用bundle管理静态库中的xib和图片资源
    • 在静态库中创建bundle 入口
      macOS下
    • xib文件的bundle,包含xib文件和xib上所加载的图片资源;最后我才发现的,xib用的图片必须和xib文件在同一个bundle中,xib才可以自动加载图片,如图


      xib的bundle
    • 图片资源的bundle,和xib的bundle创建过程一致,图片的bundle其实完全可以看做是一个文件夹

    • 至此,我创建了三个bundle,一个xib bundle,两个图片bundle(用于两个不同风格的项目,内部图片名称一样)


      还有一个XZimgBundle.bundle
    bundle如何使用
    • 首先,bundle其实是静态库中的资源,因为当前是在项目中引用静态库,所以bundle需要拖拽进项目,供项目应用,如下


      bundle拖拽入项目
    • xib又和图片资源不同,不同点在于xib会变化,修改,那就需要静态库重新编译获取xib的bundle,而图片bundle上面说了其实就是个文件夹用于管理图片,所以在image的bundle创建好之后,就可以从静态库的target中删除了,它的管理就在项目中删加图片就是了

    • 最后一点,现在bundle都在项目中了,静态库中访问Bundle其实就是在访问项目中的bundle,那怎么访问呢?我在静态库中定义了一个BundleTool

    //其中一个项目的名称是qmp_ios,这样可以判断静态库当前是哪个项目加载的
    + (BOOL)isQMP{
        return [[[NSBundle mainBundle]bundlePath]containsString:@"qmp_ios"];
    }
    //xib资源所在的bundle
    + (NSBundle *)commonBundle{
        NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"CommonBundle.bundle"];
        NSBundle *bundle1 =  [NSBundle bundleWithPath: path];
    
        return bundle1;
    }
    //qmp_ios引入的图片资源QMPimgBundle.bundle
    + (NSBundle *)qmpImgBundle{
        
        NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"QMPimgBundle.bundle"];
        NSBundle *bundle1 =  [NSBundle bundleWithPath: path];
        
        return bundle1;
    }
    //xinzhi_ios引入的图片资源XZimgBundle.bundle
    + (NSBundle *)xzImgBundle{
        NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"XZimgBundle.bundle"];
        NSBundle *bundle1 =  [NSBundle bundleWithPath: path];
        
        return bundle1;
    }
    
    + (NSString *)getBundlePath: (NSString *) assetName{
        NSBundle *myBundle = [BundleTool commonBundle];
        if (myBundle && assetName) {
            return [[myBundle resourcePath] stringByAppendingPathComponent: assetName];
        }
        return nil;
    }
    //用此类替代[UIImage imageNamed] 访问正确路径下的图片,bundle下的图片可以直接[UIImage imageNamed: bundle+图片名]
    + (UIImage*)imageNamed:(NSString*)imageName{
        if ([BundleTool isQMP]) {
            if ([imageName containsString:@"activity_user"]) {
                NSLog(@"----");
            }
            return [UIImage imageNamed:[NSString stringWithFormat:@"QMPimgBundle.bundle/%@",imageName]];
    
        }else{
            return [UIImage imageNamed:[NSString stringWithFormat:@"XZimgBundle.bundle/%@",imageName]];
        }
        
    }
    

    至此,bundle的创建和使用就此结束,而在项目内部(不牵扯静态库)用到的图片及xib和平时普通的用法还是一样的,因为项目内的Bundle就是xib和图片所在的bundle

    静态库中的类和项目中的类如何相互调用

    先讲,这种workspace机构,.a静态库只能被项目引用,不能引用项目(项目是可以引用项目的),那就意味着项目可以随意调用.a暴露出来的静态库中的类,那.a如何调用项目的类呢,以上讲了背景,我们的.a不是完全独立解耦的,项目A和B的公共业务模块还在.a里,所以.a 是存在需要调用项目业务模块的情况的;

    • 静态库想要访问项目中的类?
      如何调用? 我选择使用protocol,.a中定义了一套跳转协议AppPageSkipProtocol,和一个跳转工具类LibraryPageSkipTool(其中有一个代理属性id< AppPageSkipProtocol >delegate),需要跳转到项目中的地方,就用delegate调用跳转协议中的api去负责跳转,传入对应参数即可
    • 跳转协议根据实际情况,看是否需要传入参数,定义block回调,根据实际情况随时修改添加都可以
    • 跳转工具的delegate,在项目的didFinishLaunch里,用项目的跳转工具类实例作为delegate传给.a 的跳转工具类,如 [LibraryPageSkipTool shared].delegate = [AppPageSkipTool shared],项目的跳转工具类AppPageSkipTool内部,遵循协议AppPageSkipProtocol,实现协议方法就可以了
    如何使用cocoaPods

    上面讲过,静态库被引入项目之后,编译执行环境都是项目的环境,所以静态库需要的环境(build phases,三方库,系统库),项目中也需要实现配置,那么......

    • Podfile如何配置, 如图,静态库中用到的三方库,项目中也需要引入,项目中另外可以添加项目内部需要的库
    workspace 'WorkSpaceQMP.xcworkspace'
    target 'CommonLibrary' do
      platform :ios,'8.0'
      project 'CommonLibrary/CommonLibrary.xcodeproj'
      pod 'AFNetworking', '~> 3.1.0'
      pod 'MJRefresh', '~> 3.1.0'
      pod 'SDWebImage'
    end
    
    target 'qmp_ios' do
      platform :ios,'8.0'
      project 'qmp_ios/qmp_ios.xcodeproj'
     pod 'AFNetworking', '~> 3.1.0'
      pod 'MJRefresh', '~> 3.1.0'
      pod 'SDWebImage'
      pod 'YYText'
    
    • 在对应的.a和项目的build phases的Link build Library中添加各自的libPod库

    • 关闭workspace,此时文件目录,啊,多么愉快的feel


      最终的目录结构
    最后一个步骤,git管理

    我的一个不知道是否错了的步骤: 创建仓库并初始化——>clone到本地文件夹——>代码复制到此文件夹——>add,commit,push——>发现两个项目是空,git提示subModule的相关信息

    • 正确步骤: 创建仓库并初始化——>终端 cd到代码根目录——>git init初始化仓库,add,commit——>重点[git remote add origin 你的远程库地址] ——>获取远程库同步git pull --rebase origin master——>提交git push -u origin master
      参考:https://www.cnblogs.com/eedc/p/6168430.html
    遇到的问题
    • 实际情况下的.a 配置是很麻烦的,需要引入很多第三方库,其实整个过程和实际项目中使用是一样的,能使用pod管理的尽量使用cocoaPods管理,三方库搞定一个再导入另一个,不然你都不知道哪个库出的问题
    • 静态库配置出现arm64的问题,按照网上的做法大概就可以,千万记住,项目要配置静态库相同的环境,所需要的系统库一定全部导入,有时候这种情况也会出现arm64的问题,实际是项目没有导入需要支持的三方库
    • 先配置静态库,xcode先build静态库,.a成功了,再build项目
    • Archive问题:报错XcodeDefault.xctoolchain/usr/bin/strip: can't open temporary file:。。。,解决在.a的build setting中将strip linked product置为NO
    • 打包完成发现最终的.ipa文件特别大,比原先大了二三十兆,网上搜索一些缩减静态库的方法如下:
      1、在Build setting里面配置:
      2、set Generate Debug Symbols to NO
      3、Strip Debug Symbols During Copy flag set to Yes
      4、同时Valid Architectures可以根据实际情况缩减;
      目前Xcode默认支持iOS的指令集有armv7,armv7s,arm64;armv7只出现在iPhone4、iPhone4S的机器上;armv7s只出现在iPhone5、iPhone5C上;后面的机器一般都是arm64芯片;iPhone4、iPhone4S一般项目可以考虑不支持就在Valid Architectures将armv7删掉。(经测试,只要设置Valid Architectures就可以了,其他的设置效果不太明显)

    相关文章

      网友评论

        本文标题:workspace管理静态库和多个项目, 及cocoaPods的

        本文链接:https://www.haomeiwen.com/subject/bjukfqtx.html