首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Swift框架中导入CommonCrypto

在Swift框架中导入CommonCrypto
EN

Stack Overflow用户
提问于 2014-08-11 17:03:49
回答 16查看 111.1K关注 0票数 189

如何在Swift框架中为CommonCrypto导入iOS?

我了解如何在Swift应用程序中使用CommonCrypto:将#import <CommonCrypto/CommonCrypto.h>添加到桥接头中。但是,Swift框架不支持桥接头。文档说:

您可以导入具有纯目标C代码基、纯Swift代码基或混合语言代码基的外部框架。导入外部框架的过程是相同的,无论框架是用一种语言编写的还是包含来自两种语言的文件。导入外部框架时,请确保要导入的框架的定义模块构建设置设置为“是”。 可以使用以下语法将框架导入到不同目标中的任何Swift文件中:

代码语言:javascript
运行
复制
import FrameworkName

不幸的是,导入CommonCrypto不起作用。也没有在伞头中添加#import <CommonCrypto/CommonCrypto.h>

EN

回答 16

Stack Overflow用户

回答已采纳

发布于 2014-08-11 19:02:04

我找到了一个GitHub项目,它在Swift框架中成功地使用了CommonCrypto:SHA256 256-Swift。另外,这篇关于sqlite3中的相同问题的文章也很有用。

根据以上所述,这些步骤如下:

1)在项目目录中创建一个CommonCrypto目录。在内部创建一个module.map文件。模块映射将允许我们使用CommonCrypto库作为Swift中的一个模块。其内容如下:

代码语言:javascript
运行
复制
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文件中作为任何其他模块。例如:

代码语言:javascript
运行
复制
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。一旦我删除了这条线,它就可以了。

票数 84
EN

Stack Overflow用户

发布于 2017-03-17 08:38:32

更简单、更健壮的方法是使用运行脚本阶段创建一个名为"CommonCryptoModuleMap“的聚合目标,以自动生成模块映射,并使用正确的Xcode/SDK路径:

运行脚本阶段应该包含以下bash:

代码语言:javascript
运行
复制
# 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,可以在运行脚本阶段检查模块映射是否存在。

代码语言:javascript
运行
复制
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
票数 141
EN

Stack Overflow用户

发布于 2015-03-22 01:08:53

您实际上可以构建一个“只起作用”的解决方案(不需要像其他解决方案所要求的那样,将module.modulemapSWIFT_INCLUDE_PATHS设置复制到您的项目中),但它确实要求您创建一个虚拟框架/模块,您将适当地将其导入到框架中。我们还可以确保它不受平台(iphoneosiphonesimulatormacosx)的影响。

  1. 向项目中添加一个新的框架目标,并以系统库的名称命名它,例如,"CommonCrypto“。(您可以删除伞头,CommonCrypto.h.)
  2. 添加一个新的配置设置文件并命名它,例如,"CommonCrypto.xcconfig“。(不要检查你的目标是否包括在内。)用以下内容填充它: $(SRCROOT)/CommonCrypto/iphonesimulator.modulemap MODULEMAP_FILEsdk=iphoneos* =\$( MODULEMAP_FILEsdk=iphonesimulator* )/CommonCrypto/iphoneos.Modemap MODULEMAP_FILEsdk=iphonesimulator*=\\ MODULEMAP_FILEsdk=macosx* =\$(SRCROOT)/CommonCrypto/macosx.Modemap
  3. 创建上面引用的三个模块映射文件,并使用以下内容填充它们:

"/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/CommonCrypto.h“

代码语言:javascript
运行
复制
- **iphoneos.modulemap**

模块CommonCrypto系统{ header CommonCrypto导出*}

- iphonesimulator.modulemap

模块CommonCrypto系统{标头CommonCrypto导出*}

- macosx.modulemap

模块CommonCrypto系统{标头CommonCrypto导出*}

(如果您正在运行测试版,请将"Xcode.app“替换为"Xcode-beta.app”。如果没有运行El Capitan,则用当前的OS替换10.11。)

  1. 在项目设置的Configurations,信息选项卡上,将CommonCrypto调试发布配置设置为CommonCrypto (引用CommonCrypto.xcconfig). )
  2. 在框架目标的CommonCrypto构建阶段选项卡上,将框架添加到目标依赖项中。此外,将libcommonCrypto.dylib添加到具有库构建阶段的链接二进制文件中。
  3. 在CommonCrypto.framework产品中选择,并确保包装器的目标成员资格设置为可选

现在您应该能够在包装器框架中构建、运行和import CommonCrypto

有关示例,请参见SQLite.swift如何使用虚拟SQLite.swift

票数 95
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25248598

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档