Импорт CommonCrypto в Swift
Как вы импортируете CommonCrypto в среду Swift для iOS?
Я понимаю, как использовать CommonCrypto в приложении Swift: вы добавляете #import <CommonCrypto/CommonCrypto.h>
в заголовок моста.
- Установка индикатора активности в CollectionViewCell
- Выполнить «догонять», когда игра снова открывается
- <TargetName-Swift.h> файл не найден
- Обнаружение Scenekit Пользовательский удаленный объект
- Alamofire загружает видео из библиотеки iPhone
Однако структуры Swift не поддерживают перемычки заголовков. В документации говорится:
Вы можете импортировать внешние фреймворки с чистой базой Objective-C, чистой кодовой базой Swift или кодовой базой на смешанном языке. Процесс импорта внешней структуры одинаковый, независимо от того, написана ли среда на одном языке или содержит файлы с обоих языков. Когда вы импортируете внешнюю инфраструктуру, убедитесь, что для параметра «Определить модуль» для импортируемой структуры установлено значение «Да».
Вы можете импортировать фреймворк в любой файл Swift в другой целевой среде, используя следующий синтаксис:
import FrameworkName
К сожалению, импорт CommonCrypto
не работает. Также не добавляется #import <CommonCrypto/CommonCrypto.h>
в заголовок зонтика.
- Быстрая альтернатива для шрифтаDescriptorWithSymbolicTraits ios 8 bug
- Swift Compiler: не может индексировать значение типа «» с индексом типа «()»
- Использование RxSwift, как включить UIButton на основе допустимого текста?
- Как я могу поместить метки оси x в соответствии со своим баром?
- Могу ли я превратить строку в блок кода в swift?
- Капля тени ячейки UITableView меняет положение после прокрутки таблицы
- iOS 11: self.performSegue () не работает
- почему NSTimer работает только один раз в быстром
8 Solutions collect form web for “Импорт CommonCrypto в Swift”
Фактически вы можете создать решение, которое «просто работает» (нет необходимости копировать параметры module.modulemap и SWIFT_INCLUDE_PATHS
в ваш проект, как это требуется в других решениях здесь), но для этого требуется создать фиктивную структуру / модуль, который вы «Импорт в вашу структуру. Мы также можем обеспечить его работу независимо от платформы ( iphoneos
, iphonesimulator
или macosx
).
-
Добавьте новую цель рамки в свой проект и назовите ее после системной библиотеки, например , «CommonCrypto». (Вы можете удалить заголовок зонтика, CommonCrypto.h .)
-
Добавьте новый файл параметров конфигурации и назовите его, например , «CommonCrypto.xcconfig». (Не проверяйте ни одну из ваших целей для включения.) Заполните ее следующим образом:
MODULEMAP_FILE[sdk=iphoneos*] = \ $(SRCROOT)/CommonCrypto/iphoneos.modulemap MODULEMAP_FILE[sdk=iphonesimulator*] = \ $(SRCROOT)/CommonCrypto/iphonesimulator.modulemap MODULEMAP_FILE[sdk=macosx*] = \ $(SRCROOT)/CommonCrypto/macosx.modulemap
-
Создайте три указанных выше файла карты модулей выше и заполните их следующим образом:
-
iphoneos.modulemap
module CommonCrypto [system] { header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/CommonCrypto.h" export * }
-
iphonesimulator.modulemap
module CommonCrypto [system] { header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/CommonCrypto/CommonCrypto.h" export * }
-
macosx.modulemap
module CommonCrypto [system] { header "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/CommonCrypto/CommonCrypto.h" export * }
(Замените «Xcode.app» на «Xcode-beta.app», если вы используете бета-версию. Замените
10.11
на ваш текущий SDK SD, если не используете El Capitan.) -
-
На вкладке « Информация » параметров вашего проекта в разделе « Конфигурации» установите конфигурации « Отладка и выпуск» CommonCrypto в CommonCrypto (ссылка на CommonCrypto.xcconfig ).
-
На вкладке « Построить фазы » на вашей платформе добавьте среду CommonCrypto в Target Dependencies . Кроме того, добавьте libcommonCrypto.dylib в фазу компоновки ссылок с бинарными связями .
-
Выберите CommonCrypto.framework в продуктах и убедитесь, что для его целевого членства для вашей обертки установлено значение Необязательный .
Теперь вы сможете создавать, запускать и import CommonCrypto
в своей import CommonCrypto
.
Например, посмотрите, как SQLite.swift использует фиктивный sqlite3.framework .
Я нашел проект GitHub, который успешно использует CommonCrypto в среде Swift: SHA256-Swift . Кроме того, эта статья о той же проблеме с sqlite3 была полезна.
Исходя из вышесказанного, этапы:
1) Создайте каталог CommonCrypto
внутри каталога проекта. Внутри создайте файл module.map
. Карта модуля позволит нам использовать библиотеку CommonCrypto в качестве модуля в Swift. Его содержание:
module CommonCrypto [system] { header "/Applications/Xcode6-Beta5.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.0.sdk/usr/include/CommonCrypto/CommonCrypto.h" link "CommonCrypto" export * }
2) В настройках сборки в Swift Compiler – Search Paths добавьте каталог CommonCrypto
в Import Paths ( 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 Simulator). Я не знаю, как сделать путь заголовка относительно текущей платформы.
Обновления для iOS 8 <= Мы должны удалить строку «CommonCrypto» , чтобы получить успешную компиляцию.
редактировать
Я продолжал получать
ld: библиотека не найдена для -lCommonCrypto для архитектуры x86_64 clang: ошибка: команда компоновщика не удалась с кодом выхода 1 (используйте -v, чтобы увидеть вызов)
Если я не удалил link "CommonCrypto"
. Как только я удалил эту строку, она построена нормально.
Что-то более простое и надежное заключается в создании целевой совокупности, называемой «CommonCryptoModuleMap», с этапом сценария запуска для автоматического создания карты модуля и с правильным ходом Xcode / SDK:
Этап запуска сценария должен содержать этот bash:
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
Использование кода оболочки и ${SDKROOT}
означает, что вам не нужно жестко кодировать путь Xcode.app, который может варьироваться от системы к системе, особенно если вы используете xcode-select
для перехода на бета-версию или используете CI, где несколько версий установлены в нестандартных местах. Вам также не нужно жестко кодировать SDK, поэтому это должно работать для iOS, macOS и т. Д. Вам также не нужно ничего сидеть в исходном каталоге вашего проекта.
Создав эту цель, сделайте свою библиотеку / фреймворк зависимой от нее с помощью элемента Target Dependencies:
Это обеспечит создание карты модуля до создания вашей структуры.
Затем добавьте родительский каталог карты модуля, ${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap
, в настройку сборки «Header Search Paths»:
Не забудьте добавить $(inherited)
строку, если у вас есть пути поиска, определенные на уровне проекта или xcconfig.
Вот и все, теперь вы должны иметь возможность import CommonCrypto
В этом ответе обсуждается, как заставить его работать внутри рамки, а также с Cocoapods и Carthage
🐟 Подход модуля
Я использую modulemap
в своей обертке вокруг CommonCrypto https://github.com/onmyway133/arcane , https://github.com/onmyway133/Reindeer
Для тех, кто не получил header not found
, посмотрите https://github.com/onmyway133/Arcane/issues/4
-
Создайте папку
CCommonCrypto
содержащуюmodule.modulemap
module CCommonCrypto { header "/usr/include/CommonCrypto/CommonCrypto.h" export * }
-
Перейдите в «Встроенные параметры» -> «Импорт путей»
${SRCROOT}/Sources/CCommonCrypto
🌳 Cocoapods с модульным подходом
-
Здесь находится podspec https://github.com/onmyway133/Arcane/blob/master/Arcane.podspec
s.source_files = 'Sources/**/*.swift' s.xcconfig = { 'SWIFT_INCLUDE_PATHS' => '$(PODS_ROOT)/CommonCryptoSwift/Sources/CCommonCrypto' } s.preserve_paths = 'Sources/CCommonCrypto/module.modulemap'
-
Использование
module_map
не работает, см. https://github.com/CocoaPods/CocoaPods/issues/5271 -
Использование Local Development Pod с
path
не работает, см. https://github.com/CocoaPods/CocoaPods/issues/809 -
Вот почему вы видите, что мой пример Podfile https://github.com/onmyway133/CommonCrypto.swift/blob/master/Example/CommonCryptoSwiftDemo/Podfile указывает на git repo
target 'CommonCryptoSwiftDemo' do pod 'CommonCryptoSwift', :git => 'https://github.com/onmyway133/CommonCrypto.swift' end
🐘 подход с открытым заголовком
-
Ji является оберткой вокруг libxml2 и использует подход с открытым заголовком
-
Он имеет заголовочный файл https://github.com/honghaoz/Ji/blob/master/Source/Ji.h с
Target Membership
установленным вPublic
-
Он имеет список файлов заголовков для libxml2 https://github.com/honghaoz/Ji/tree/master/Source/Ji-libxml
-
У него есть настройки сборки -> пути поиска заголовков
$(SDKROOT)/usr/include/libxml2
-
У него есть параметры настройки -> Другие флаги компоновщика
-lxml2
🐏 Cocoapods с подходом общего заголовка
-
Взгляните на podspec https://github.com/honghaoz/Ji/blob/master/Ji.podspec
s.libraries = "xml2" s.xcconfig = { 'HEADER_SEARCH_PATHS' => '$(SDKROOT)/usr/include/libxml2', 'OTHER_LDFLAGS' => '-lxml2' }
🐝 Интересные связанные должности
- Как позвонить в С из Свифта?
- https://spin.atomicobject.com/2015/02/23/c-libraries-swift/
Модульные решения могут быть хорошими и надежными в отношении изменений SDK, но я нашел их неудобными для использования на практике, и не настолько надежными, как хотелось бы, когда передавали вещи другим. Чтобы попытаться сделать все более надежным, я пошел по-другому:
Просто скопируйте заголовки.
Я знаю, хрупкий. Но Apple почти никогда не вносит существенных изменений в CommonCrypto, и я живу мечтой, что они не изменят ее каким-либо существенным образом, не превратив CommonCrypto в модульный заголовок.
«Скопируйте заголовки», я имею в виду «вырезать и вставить все заголовки, которые вам нужны, в один массивный заголовок в вашем проекте, как это сделал бы препроцессор». В качестве примера этого можно скопировать или адаптироваться, см. RNCryptor.h .
Обратите внимание, что все эти файлы лицензированы в APSL 2.0, и этот подход намеренно поддерживает уведомления об авторских правах и лицензиях. Мой этап конкатенации лицензируется в рамках MIT и распространяется только на следующее уведомление о лицензии).
Я не говорю, что это прекрасное решение, но до сих пор это было невероятно простое решение как для реализации, так и для поддержки.
@mogstad был достаточно любезен, чтобы обернуть решение @stephencelis в Cocoapod:
pod 'libCommonCrypto'
Другие доступные мне стручки не работали для меня.
Я знаю, что это старый вопрос. Но я выясню альтернативный способ использования библиотеки в проекте Swift, что может быть полезно для тех, кто не хочет импортировать фреймворк, введенный в эти ответы.
В проекте Swift создайте заголовок моста Objective-C, создайте категорию NSData (или пользовательский класс, который будет использовать библиотеку) в Objective-C. Единственным недостатком будет то, что вы должны написать весь код реализации в Objective-C. Например:
#import "NSData+NSDataEncryptionExtension.h" #import <CommonCrypto/CommonCryptor.h> @implementation NSData (NSDataEncryptionExtension) - (NSData *)AES256EncryptWithKey:(NSString *)key { //do something } - (NSData *)AES256DecryptWithKey:(NSString *)key { //do something }
А затем в своем заголовочном заголовке цели-c добавьте это
#import "NSData+NSDataEncryptionExtension.h"
И тогда в классе Свифт делайте похожие вещи:
public extension String { func encryp(withKey key:String) -> String? { if let data = self.data(using: .utf8), let encrypedData = NSData(data: data).aes256Encrypt(withKey: key) { return encrypedData.base64EncodedString() } return nil } func decryp(withKey key:String) -> String? { if let data = NSData(base64Encoded: self, options: []), let decrypedData = data.aes256Decrypt(withKey: key) { return decrypedData.UTF8String } return nil } }
Он работает так, как ожидалось.
Это очень просто. Добавить
#import <CommonCrypto/CommonCrypto.h>
в файл .h (заголовок заголовочного файла вашего проекта). В качестве конвенции вы можете назвать это YourProjectName-Bridging-Header.h.
Затем перейдите в свой проект Build Settings и найдите Swift Compiler – Code Generation. Под ним добавьте имя вашего заголовка моста к записи «Objetive-C Bridging Header».
Все готово. Импорт не требуется в вашем коде Swift. Любые общедоступные заголовки Objective-C, перечисленные в этом файле заголовка моста, будут видны для Swift.