如何在Swift框架中为CommonCrypto导入iOS?
我了解如何在Swift应用程序中使用CommonCrypto:将#import <CommonCrypto/CommonCrypto.h>添加到桥接头中。但是,Swift框架不支持桥接头。文档说:
您可以导入具有纯目标C代码基、纯Swift代码基或混合语言代码基的外部框架。导入外部框架的过程是相同的,无论框架是用一种语言编写的还是包含来自两种语言的文件。导入外部框架时,请确保要导入的框架的定义模块构建设置设置为“是”。 可以使用以下语法将框架导入到不同目标中的任何Swift文件中:
import FrameworkName不幸的是,导入CommonCrypto不起作用。也没有在伞头中添加#import <CommonCrypto/CommonCrypto.h>。
发布于 2014-08-11 19:02:04
我找到了一个GitHub项目,它在Swift框架中成功地使用了CommonCrypto:SHA256 256-Swift。另外,这篇关于sqlite3中的相同问题的文章也很有用。
根据以上所述,这些步骤如下:
1)在项目目录中创建一个CommonCrypto目录。在内部创建一个module.map文件。模块映射将允许我们使用CommonCrypto库作为Swift中的一个模块。其内容如下:
module CommonCrypto [system] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.0.sdk/usr/include/CommonCrypto/CommonCrypto.h"
link "CommonCrypto"
export *
}2)在Build中,在Swift编译器搜索路径中,将CommonCrypto目录添加到导入路径(SWIFT_INCLUDE_PATHS)中。

3)最后,将CommonCrypto导入Swift文件中作为任何其他模块。例如:
import CommonCrypto
extension String {
func hnk_MD5String() -> String {
if let data = self.dataUsingEncoding(NSUTF8StringEncoding)
{
let result = NSMutableData(length: Int(CC_MD5_DIGEST_LENGTH))
let resultBytes = UnsafeMutablePointer<CUnsignedChar>(result.mutableBytes)
CC_MD5(data.bytes, CC_LONG(data.length), resultBytes)
let resultEnumerator = UnsafeBufferPointer<CUnsignedChar>(start: resultBytes, length: result.length)
let MD5 = NSMutableString()
for c in resultEnumerator {
MD5.appendFormat("%02x", c)
}
return MD5
}
return ""
}
}局限性
在另一个项目中使用自定义框架会在编译时由于错误missing required module 'CommonCrypto'而失败。这是因为自定义框架中似乎没有包含CommonCrypto模块。解决方法是在使用框架的项目中重复步骤2(设置Import Paths)。
模块映射不是独立于平台的(它目前指向特定的平台,iOS 8模拟器)。我不知道如何使标题路径相对于当前平台。
iOS 8 <=的更新我们应该删除行链接"CommonCrypto",以获得成功的编译。
更新/编辑
我一直收到以下生成错误:
ld:未找到用于体系结构的-lCommonCrypto库x86_64 clang: x86_64: linker命令失败,退出代码1(使用-v查看调用)
除非我从我创建的link "CommonCrypto"文件中删除了行module.map。一旦我删除了这条线,它就可以了。
发布于 2017-03-17 08:38:32
更简单、更健壮的方法是使用运行脚本阶段创建一个名为"CommonCryptoModuleMap“的聚合目标,以自动生成模块映射,并使用正确的Xcode/SDK路径:


运行脚本阶段应该包含以下bash:
# This if-statement means we'll only run the main script if the CommonCryptoModuleMap directory doesn't exist
# Because otherwise the rest of the script causes a full recompile for anything where CommonCrypto is a dependency
# Do a "Clean Build Folder" to remove this directory and trigger the rest of the script to run
if [ -d "${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap" ]; then
echo "${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap directory already exists, so skipping the rest of the script."
exit 0
fi
mkdir -p "${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap"
cat <<EOF > "${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap/module.modulemap"
module CommonCrypto [system] {
header "${SDKROOT}/usr/include/CommonCrypto/CommonCrypto.h"
export *
}
EOF使用shell代码和${SDKROOT}意味着您不必硬编码系统间的Xcode.app路径,特别是如果您使用xcode-select切换到beta版本,或者构建在一个CI服务器上,在非标准位置安装多个版本。您也不需要硬编码SDK,所以这应该适用于iOS、macOS等。您也不需要在项目的源目录中有任何东西。
在创建这个目标之后,让您的库/框架使用一个目标依赖项来依赖它:

这将确保在构建框架之前生成模块映射。
macOS注意到:如果您也支持macOS,则需要将macosx添加到您刚刚创建的新聚合目标的Supported Platforms构建设置中,否则它将不会将模块映射与其他框架产品放在正确的Debug派生数据文件夹中。

接下来,将模块映射的父目录${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap添加到Swift部分(SWIFT_INCLUDE_PATHS)下的“导入路径”构建设置中:

如果在项目或xcconfig级别上定义了搜索路径,请记住添加$(inherited)行。
就这样,你现在应该可以import CommonCrypto了
Xcode 10的更新
Xcode 10现在附带了一个CommonCrypto模块映射,这样就没有必要解决这个问题了。如果您想同时支持Xcode 9和10,可以在运行脚本阶段检查模块映射是否存在。
COMMON_CRYPTO_DIR="${SDKROOT}/usr/include/CommonCrypto"
if [ -f "${COMMON_CRYPTO_DIR}/module.modulemap" ]
then
echo "CommonCrypto already exists, skipping"
else
# generate the module map, using the original code above
fi发布于 2015-03-22 01:08:53
您实际上可以构建一个“只起作用”的解决方案(不需要像其他解决方案所要求的那样,将module.modulemap和SWIFT_INCLUDE_PATHS设置复制到您的项目中),但它确实要求您创建一个虚拟框架/模块,您将适当地将其导入到框架中。我们还可以确保它不受平台(iphoneos、iphonesimulator或macosx)的影响。
"/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/CommonCrypto.h“
- **iphoneos.modulemap**模块CommonCrypto系统{ header CommonCrypto导出*}
- iphonesimulator.modulemap
模块CommonCrypto系统{标头CommonCrypto导出*}
- macosx.modulemap
模块CommonCrypto系统{标头CommonCrypto导出*}
(如果您正在运行测试版,请将"Xcode.app“替换为"Xcode-beta.app”。如果没有运行El Capitan,则用当前的OS替换10.11。)
现在您应该能够在包装器框架中构建、运行和import CommonCrypto。
有关示例,请参见SQLite.swift如何使用虚拟SQLite.swift
https://stackoverflow.com/questions/25248598
复制相似问题