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

项目背景

项目需求:
在已有项目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
    如果Git pull报错: refusing to merge unrelated histories的解决办法,执行下面的命令:git pull origin master --allow-unrelated-histories就可以了
    参考:(https://www.cnblogs.com/xiangxinhouse/p/8254120.html)

创建本地库和fetch远程分支这些前面的步骤这里略过。可以自行百度。

解决办法:

1.cmd进入项目的根目录。

2.执行下面的命令:git pull origin master --allow-unrelated-histories。可以提交成功。

参考: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就可以了,其他的设置效果不太明显)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容