Swift库资源文件获取

库资源包括图片、xib、xib对应的图片、以及其它文件等。

本文只分析总结获取图片资源文件中所遇到的坑;大致原理其实都是一样,当你真正理解了其中的原理再获取其它资源是一样的容易。

我们制作的库有动态库、静态库之分;首先理解下:

Bundle

我们构建的app以及framework都是一个bundle,它又主要分为2种:

1)Bundle.main

The main bundle lets you access the resources in the same directory as the currently running executable. For a running app, the main bundle offers access to the app’s bundle directory. For code running in a framework, the main bundle offers access to the framework’s bundle directory.

可以理解为构建的.app就是一个main bundle

2)Bundle(for: AnyClass)

The NSBundle object that dynamically loaded aClass (a loadable bundle), the NSBundle object for the framework in which aClass is defined, or the main bundle object if aClass was not dynamically loaded or is not defined in a framework.

通过在framework中定义的class返回一个bundle对象,如果没有定义或者动态加载那么返回的是main bundle,这里没有动态加载的意思就是我们平时制作的.a或者framework静态库返回的其实和main bundle是一样的。

本文调试开发的库是Swift版本,且framework静态库,并且这个库目前只有一个subspec子模块Extension(多个也是一样的),目录结构如下:

image

pod依赖可以在framework静态库以及源码进行切换,而上面已经说了如果是静态库,那么获取资源文件和宿主工程其实是一样的,怎么调试都能获取到资源文件,比较简单,如:

Bundle.main.loadNibNamed(<#T##name: String##String#>, owner: <#T##Any?#>, options: <#T##[AnyHashable : Any]?#>)

UIImage(named: <#T##String#>)

这种情况就不讨论了;

所以本文仅仅是调试验证在pod源码依赖(并且宿主app打包是通过动态库的形式,如果是静态库那么和上面一样比较简单就不讨论了)的情况进行开发调试。

为啥要研究这块?

因为你做好的库,并不确定对方拿到后在宿主工程中到底是以静态库的形式打包还是动态库的形式,所以为了通用性,必须都得实现。

1、Bundle(for: Self.self)

不能这样写,因为如果当前扩展子模块中是对UIImageView写的一个扩展,那么这里的self就表示的是UIImageView,而UIImageView是系统动态库里面定义的,所以得到的是:

image

系统的UIKitCore动态库。

2、查看Example.app里面的内容

选择target为Example,进行编译:

image

查看包里面的内容:

image

这就是扩展里面的资源bundle,查看里面的资源文件发现实际是放了2层,即framework--->Extension.bundle---->Extension.bundle/xxx.png,为什么呢?

是因为podspec挂载资源文件区别导致的

sp.resource_bundles = {
        'Extension' => ['xxx/Assets/xxx.bundle']
    }
sp.resource = 'xxx/Assets/xxx.bundle'

resource_bundles如果podfile控制不管是源码依赖还是库依赖打包成静态库或者动态库,那么生成的bundle资源文件都会被再包裹一层;xxx.bundle/xxx.bundle/.png

resource资源文件不会被包裹,只有一层。

这2种我们应该用哪一个呢?CocoaPods官方是强烈推荐用第一种,为了避免和main bundle中的资源文件名字冲突:

For building the Pod as a static library, we strongly recommend library developers to adopt resource bundles as there can be name collisions using the resources attribute.

现在很多第三方库带资源文件的不少使用的是第二种,其实如果按照规范,对应的bundle前面加上自己的库名字,这种冲突几率是很小的。

3、定义一个Class

为什么还要单独定义一个类呢?我们这里有1个特殊性,就是我们这里的子模块是一个Extension扩展,都是Swift系统库中Class的扩展,所以为了获取到当前bundle必须自定义一个class,我们这里创建一个xxExtension.swift,然后在Example中进行调试:

(lldb) po Bundle(for: xxExtension.self)
NSBundle </Users/xx/Library/Developer/CoreSimulator/Devices/700BD15-4005-4C6B-943B-73CA56C020F/data/Containers/Bundle/Application/996818F0-9F7A-42DC-A02D-066A32B5E940/xxBaseModule_Example.app> (loaded)

(lldb) po Bundle.main
NSBundle </Users/xx/Library/Developer/CoreSimulator/Devices/700BD15-4005-4C6B-943B-73CA56C020F/data/Containers/Bundle/Application/996818F0-9F7A-42DC-A02D-066A32B5E940/xxBaseModule_Example.app> (loaded)

(lldb) 

????

为啥会是一样的?都是main bundle?官方文档不是说Bundle(for: AnyClass)中如果传入的是库中定义的类,应该返回的是xxBaseModule.framework才对,为啥不对???

原因:

还记得我们最上面的工程目录结构吗,project中有2个target,一个是我们的Example,一个是子Extension静态库的源码,而pod中是Development Pods本地私有库。

问题就出在Extension对应的target那里,我们当初创建它的目的是可以很方便的给这个组件库调试修改bug、增加功能等;虽然podfile中有引入这个组件,但是实际上我们Example中import的是import Extension 子模块,并不是基础模块xxBaseModule,而这个Extension对应的building我们当初定义的是一个静态库,所以无论你podfile如何更改,这里获取到的肯定是main bundle,那么我们要模拟pod源码依赖且动态库打包到宿主工程,我们应该如何做???

修改Extension对应的building为动态库。

4、Extension.framework和xxBaseModule.framework

编译后再次查看.app里面的内容,你会看到:

image

为啥获取到的是Extension.framework???

应该是xxBaseModule.framework才对啊,并且看上面截图也知道资源文件是放在这个里面的。

原因:

其实这里也还是因为上面Example项目中Extension对应的target导致的,这个时候就得新创建一个项目,通过podfile导入进行测试,正确。

其实这里是不用这么麻烦再创建一个新项目来验证的,目的是为了让自己能更清晰的理解bundle以及这里Example项目产生bug的原因。

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