Cocoapods從1.5.3版本開始起引入Swift靜態庫不再需要在Podfile中添加`use_frameworks!`了。源碼引入Swift庫代碼後生成的Target將會是.a的形式。

下面說一下具體的接入方式。

1.將Pod版本改為1.5.3或更高版本

如果是在Gemfile中指定的pod版本,可以這樣修改:

gem cocoapods, ~> 1.5.3

Pod版本改成1.5版本之後可能會遇到OC頭文件引入報錯的問題。比如有些OC庫中引入AFNetworking的頭文件這樣寫:

#import <AFNetworking.h>

那麼在Pod 1.5.0之後版本就會報錯:`file not found with angled include use quotes instead`, 其實嚴格頭文件引入應該這樣寫:

#import <AFNetworking/AFNetworking.h>

這個錯誤怎樣解決呢?可以在Podfile的post_install鉤子中修改OC庫的header search path, 添加自己依賴的pod的header路徑:

platform = OpenStruct.new(name: :ios)
public_headers = installer.sandbox.public_headers.search_paths(platform)
installer.pods_project.build_configurations.each do |config|
config.build_settings[HEADER_SEARCH_PATHS] = public_headers.join( )
end

2.在Podfile中添加我們需要引入的Swift Pod

pod DEFImageUploader, 0.1.0

3.Pod install後在項目中使用Swift庫

  • 3.1 在Swift中使用

import DEFImageUploader

  • 3.2 在OC中使用

@import DEFImageUploader;


在OC中引入Swift Pod庫可能遇到的問題

在上面3.2中提到的是以Module的方式import需要使用的Swift庫的。這個前提是Xcode工程的`Enable Module`必須是打開的。

  1. 挑戰0x1

但是我們項目中使用了Ccache這個工具來為項目編譯加速。但是Ccache使用的前提是要把Xcode工程的`Enable Module`設置關閉。這樣一來在OC中就無法使用`@import DEFImageUploader;`的方式來引入Swift庫,要改為`#import <DEFImageUploader/DEFImageUploader-Swift.h>`的方式引入。

為了兼容Ccache關閉Module

2. 挑戰0x2

我們使用`#import <DEFImageUploader/DEFImageUploader-Swift.h>`來引入頭文件後報錯,大意就說`DEFImageUploader-Swift.h`這個橋接頭文件找不到,不論怎麼修改引入方式,比如

#import <DEFImageUploader-Swift.h>

還有

#import "DEFImageUploader-Swift.h"

的引入方式都會報錯。

其實`DEFImageUploader-Swift.h`橋接頭文件已經生成了。

Cocoapods在`DEFImageUploader`的target的Build Phases中自動添加了一個`Copy generated compatibility header`的Script,將`DEFImageUploader-Swift.h`拷貝到了`${BUILT_PRODUCTS_DIR}/Swift Compatibility Header`路徑下。

`Copy generated compatibility header`腳本內容如下:

COMPATIBILITY_HEADER_PATH="${BUILT_PRODUCTS_DIR}/Swift Compatibility Header/${PRODUCT_MODULE_NAME}-Swift.h"
MODULE_MAP_PATH="${BUILT_PRODUCTS_DIR}/${PRODUCT_MODULE_NAME}.modulemap"

ditto "${DERIVED_SOURCES_DIR}/${PRODUCT_MODULE_NAME}-Swift.h" "${COMPATIBILITY_HEADER_PATH}"
ditto "${PODS_ROOT}/Headers/Public/DEFImageUploader/DEFImageUploader.modulemap" "${MODULE_MAP_PATH}"
ditto "${PODS_ROOT}/Headers/Public/DEFImageUploader/DEFImageUploader-umbrella.h" "${BUILT_PRODUCTS_DIR}"
printf "

module ${PRODUCT_MODULE_NAME}.Swift {
header "${COMPATIBILITY_HEADER_PATH}"
requires objc
}
" >> "${MODULE_MAP_PATH}"

但是`DEFImageUploader-Swift.h`頭文件這麼拷貝的路徑是在`DerivedData`下,在Xcode項目中的Header Search Path中確是"${PODS_ROOT}/Headers/Public"。

這個路徑展開就是在`項目根路徑/Pods/Headers/Public`, 這個路徑明顯跟上面的`${BUILT_PRODUCTS_DIR}/Swift Compatibility Header`不一樣,怪不得會找不到頭文件報錯。

既然問題已經發現了怎麼解決呢? 我的方法是在Podfile中添加一段腳本,讓項目每次編譯後將`DEFImageUploader-Swift.h`從原本的`DerivedData`路徑拷貝到`項目根路徑/Pods/Headers/Public/DEFImageUploader/`路徑下。

這段腳本放在Podfile中的post_install鉤子中,具體代碼如下:

post_install do |installer|
installer.pods_project.targets.each do |target|
compatibilityPhase = target.build_phases.find { |ph| ph.display_name == Copy generated compatibility header }
if compatibilityPhase
build_phase = target.new_shell_script_build_phase(Copy Swift Generated Header)
build_phase.shell_script = <<-SH.strip_heredoc
COMPATIBILITY_HEADER_PATH="${BUILT_PRODUCTS_DIR}/Swift Compatibility Header/${PRODUCT_MODULE_NAME}-Swift.h"
ditto "${COMPATIBILITY_HEADER_PATH}" "${PODS_ROOT}/Headers/Public/${PRODUCT_MODULE_NAME}/${PRODUCT_MODULE_NAME}-Swift.h"
SH
end
end
end

代碼大意就是做拷貝`-Swift.h`橋接頭文件的事情。

這個腳本會在Pod每次編譯後執行,這樣在項目代碼中引入`#import <DEFImageUploader/DEFImageUploader-Swift.h>`就不會報錯了。


推薦閱讀:
相关文章