iOS中Pod库资源引用探究
前言
Cocoapods
中Pod
引用资源的方式有多种,不同的方式对资源的使用还是有区别的,但也有一定的规律,这里我用一个样例工程来进行说明,样例工程名叫:AssetsDemo
,使用pod lib create AssetsDemo
命令创建,目录结构如图:
这个pod
很简单,Classes
目录只有一个cell
的swift
和xib
文件,Assets
目录有一些图片资源,其中的TestTableViewCell.xib
使用了这张test
图片。目录结构如下:
├── Assets
│ ├── Images.xcassets
│ │ ├── Contents.json
│ │ └── test.imageset
│ │ ├── Contents.json
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ └── [email protected]
└── Classes
├── TestTableViewCell.swift
└── TestTableViewCell.xib
前期工作已经准备完毕,下面说下xib
和图片
资源不同使用方式下的区别:
将xib
放入source_files
,图片放入resource_bundles
在podspec
的写法如下:
ruby
s.source_files = 'AssetsDemo/Classes/**/*'
s.resource_bundles = {
'AssetsDemo' => ['AssetsDemo/{Assets,Classes}/**/*.{xcassets,png}']
}
运行后会生成这样的framework
:
我们可以看到,xib
后缀会变成nib
,并被放入framework
中,而图片资源被放入了AssetsDemo.bundle
中。
这样的结构,显然在常规情况下,xib
是没法找到图片并显示的。但是有一种有缺陷的用法可以勉强解决这个问题,那就是直接把png图片打包到AssetsDemo.bundle
中,然后在xib
中将图片名改为AssetsDemo.bundle/图片名
。这样做会导致xib
编辑时无法正确的显示图片,也没法使用xcassets
目录来存储图片,并且会导致一些系统优化无法生效。不推荐这样使用
将xib
和图片
都放入resources
在podspec
的写法如下:
ruby
s.source_files = 'AssetsDemo/Classes/**/*.swift'
s.resources = 'AssetsDemo/{Assets,Classes}/**/*.{xcassets,png,xib}'
网上有说法使用resources
来指定资源,被指定的资源只会简单的被 copy到目标工程中(主工程),资源的使用会简化,但是会与主工程同名资源文件产生冲突。但是在Xcode13
和pod 1.11.2
版本下,实测不是这样的。官方的文档也不是这样说的Podspec Syntax Reference v1.11.2,它是分静态库和动态库场景,静态库才有这类问题。
上述配置运行后会生成这样的framework
结构:
从上图可以看到,资源被直接放入了所在的framework
,另外查看主工程的包文件,是没有这些资源的。综上所述,可以得出结论,动态库中,resources
指定的资源,会被直接copy
到framework
,不会与主工程资源文件冲突。
另外,由于xib文件TestTableViewCell.nib
和Assets.car
在同一个目录下,xib
可以直接从Assets.car
中找到图片资源并正确展示
- 在主工程中打开这个
xib
文件,如果主工程中有同名资源,那么编辑时会优先显示主工程的资源,但是实际运行时还是这个pod
的资源。- 这里
xib
可以放入source_files
和resources
,效果是一样的
将xib
和图片
都放入resource_bundles
在podspec
的写法如下:
ruby
s.source_files = 'AssetsDemo/Classes/**/*.swift'
s.resource_bundles = {
'AssetsDemo' => ['AssetsDemo/{Assets,Classes}/**/*.{xcassets,png,xib}']
}
上述配置运行后会生成这样的framework
结构:
从上图可以看到,xib文件TestTableViewCell.nib
和Assets.car
在同一个目录下,xib
可以直接从Assets.car
中找到图片资源并正确展示。其中,test1
图片虽然没有以xcassets
格式引入,但是也能直接找到并正确展示。
总结
综上所述,我们可以得出一个原则:尽量让xib
和xcassets
与图片在同一个目录下,这样xib可以直接找到图片并正常展示。
关于resources
和resource_bundles
,在动态库下,他们最终效果差不多,只是resource_bundles
会把资源封装在bundle
中,使用的时候会稍微麻烦一点:
```swift
// 使用resources的情况:
let myBundle = Bundle(for: TestTableViewCell.self)
tableView.register(UINib.init(nibName: "TestTableViewCell", bundle: myBundle),
forCellReuseIdentifier: "cell")
// 使用resource_bundles的情况: let myBundle = Bundle(for: TestTableViewCell.self) let path = myBundle.path(forResource: "AssetsDemo", ofType: "bundle")! let assetsBundle = Bundle.init(path: path) tableView.register(UINib.init(nibName: "TestTableViewCell", bundle: assetsBundle), forCellReuseIdentifier: "cell")
``
至于静态库,则推荐使用
resource_bundles了。综合来看,不管是静态库还是动态库,都推荐使用
resource_bundles来引入所有的资源,因为
resources方式在静态库和动态库场景,资源的使用方法差异太大,而
resource_bundles`各场景是一致的。
至于source_files
,它只能引入代码和xib文件,不支持引入图片等其它资源。不建议用source_files
方式引入xib
,如果一定要使用,要注意避免出现xib
中图片无法加载的问题。
参考资料
by: 星的天空