Как вы импортируете CommonCrypto
в платформу Swift для iOS?
Я понимаю, как использовать CommonCrypto
в приложении Swift: вы добавляете #import <CommonCrypto/CommonCrypto.h>
в заголовок моста. Однако фреймворки Swift не поддерживают заголовки моста. В документации говорится:
Вы можете импортировать внешние платформы с чистой кодовой базой Objective-C, чистой кодовой базой Swift или смешанной кодовой базой. Процесс импорта внешнего каркаса одинаков, независимо от того, написан он на одном языке или содержит файлы на обоих языках. При импорте внешней платформы убедитесь, что для параметра сборки Defines Module для импортируемой платформы установлено значение «Да».
Вы можете импортировать фреймворк в любой файл Swift в другую цель, используя следующий синтаксис:
import FrameworkName
К сожалению, импорт CommonCrypto
не работает. Точно так же и добавление #import <CommonCrypto/CommonCrypto.h>
в заголовок зонтика.
источник
Ответы:
Что-то более простое и надежное - создать цель Aggregate под названием «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
Использование кода оболочки и
${SDKROOT}
означает, что вам не нужно жестко кодировать путь Xcode.app, который может варьироваться от системы к системе, особенно если вы используетеxcode-select
для перехода на бета-версию или строите на сервере CI, на котором установлено несколько версий в нестандартных локациях. Вам также не нужно жестко кодировать SDK, так что это должно работать для iOS, macOS и т. Д. Вам также не нужно ничего хранить в исходном каталоге вашего проекта.После создания этой цели сделайте вашу библиотеку / фреймворк зависимой от нее с помощью элемента Target Dependencies:
Это обеспечит создание карты модуля до создания вашего фреймворка.
Примечание для macOS : если вы также поддерживаете
macOS
, вам нужно будет добавитьmacosx
вSupported Platforms
настройку сборки новую совокупную цель, которую вы только что создали, иначе карта модуля не будет помещена в правильнуюDebug
папку производных данных с остальной частью каркасные изделия.Затем добавьте родительский каталог карты модуля в
${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap
параметр сборки «Import Paths» в разделе Swift (SWIFT_INCLUDE_PATHS
):Не забудьте добавить
$(inherited)
строку, если у вас есть пути поиска, определенные на уровне проекта или xcconfig.Вот и все, теперь вы можете
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
источник
На самом деле вы можете создать решение, которое «просто работает» (нет необходимости копировать 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 ОС, если не работает El Capitan.)На вкладке « Информация » параметров вашего проекта в разделе « Конфигурации» установите для конфигураций отладки и выпуска CommonCrypto значение CommonCrypto (ссылка на CommonCrypto.xcconfig ).
На вкладке Build Phases целевой платформы добавьте платформу CommonCrypto в Target Dependencies . Дополнительно добавьте libcommonCrypto.dylib на этап сборки Link Binary With Libraries .
Выберите CommonCrypto.framework в продуктах и убедитесь, что для его целевого членства для вашей оболочки установлено значение Необязательно .
Теперь у вас должна быть возможность создавать, запускать и использовать
import CommonCrypto
свою оболочку.В качестве примера посмотрите, как SQLite.swift использует фиктивный sqlite3.framework .
источник
ld: cannot link directly with /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.2.sdk/usr/lib/system/libcommonCrypto.dylib. Link against the umbrella framework 'System.framework' instead. for architecture x86_64
System.framework
хотя мне не нужно было связывать . Стоит отметить, что вам необходимо создать отдельный фреймворк для Mac и iOS, если ваш фреймворк кроссплатформенный.Я нашел проект GitHub, который успешно использует CommonCrypto в среде Swift: SHA256-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) В настройках сборки в 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). Я не знаю, как сделать путь заголовка относительно текущей платформы.
Обновления для iOS 8 <= Мы должны удалить строковую ссылку «CommonCrypto» , чтобы компиляция прошла успешно.
ОБНОВЛЕНИЕ / РЕДАКТИРОВАНИЕ
Я продолжал получать следующую ошибку сборки:
Если только я не удалил строку
link "CommonCrypto"
изmodule.map
созданного мной файла. Как только я удалил эту строку, все заработало нормально.источник
$SDKROOT
переменная должна позволять вам использовать независимые от платформы пути, но я понятия не имею, как добраться до этого в Swift.link "CommonCrypto"
из файла module.map.В этом ответе обсуждается, как заставить его работать внутри фреймворка, а также с Cocoapods и Carthage.
🐟 подход с использованием карты модулей
Я использую
modulemap
в своей оболочке вокруг CommonCrypto https://github.com/onmyway133/arcane , https://github.com/onmyway133/ReindeerДля тех
header not found
, кто получает , посмотрите https://github.com/onmyway133/Arcane/issues/4 или запуститеxcode-select --install
Сделайте папку,
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Вот почему вы видите, что мой пример подфайла https://github.com/onmyway133/CommonCrypto.swift/blob/master/Example/CommonCryptoSwiftDemo/Podfile указывает на репозиторий git
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
У него есть настройки сборки -> Другие флаги компоновщика
🐏 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' }
🐝 Интересные посты по теме
источник
/CommonCrypto/CommonCrypto.h
пределахApplications/XCode.app/Contents/Developer/Platforms/iPhoneOS....
, которые требуют ручной модификации для людей , которые переименовали XCode. Переключение этой строки для просмотра,"/usr/include/CommonCrypto/CommonCrypto.h"
похоже, отлично работает для команды с несколькими версиями XCode. Спасибо огромное!pod lib lint
, но сборка завершилась ошибкой: нет такого модуля CommonCrypto. Как я могу с этим справиться.$(PODS_ROOT)/CommonCryptoSwift/Sources/CCommonCrypto
на$(PODS_TARGET_SRCROOT)/Sources/CCommonCrypto
.PODS_TARGET_SRCROOT
установлен правильно для локальных модулей.Хорошие новости! Swift 4.2 (Xcode 10) наконец-то предоставляет CommonCrypto!
Просто добавьте
import CommonCrypto
в свой быстрый файл.источник
CommonCrypto
модуля, таким образом подозревая Apple, теперь, если я удалил свой обходной путь и вот! Это правда. Я написал об этом в Твиттере, и инженер Apple ответил, что это было задумано.ВНИМАНИЕ: iTunesConnect может отклонять приложения, использующие этот метод.
Новый член моей команды случайно сломал решение, данное одним из лучших ответов, поэтому я решил объединить его в небольшом проекте- оболочке под названием CommonCryptoModule . Вы можете установить его вручную или через Cocoapods:
pod 'CommonCryptoModule', '~> 1.0.2'
Затем все, что вам нужно сделать, это импортировать нужный модуль
CommonCrypto
, например:import CommonCryptoModule
Надеюсь, кому-то это пригодится.
источник
Я думаю, что у меня есть улучшение по сравнению с превосходной работой Майка Веллера.
Добавьте фазу выполнения сценария перед
Compile Sources
фазой, содержащей этот bash:# This if-statement means we'll only run the main script if the # CommonCrypto.framework 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 FRAMEWORK_DIR="${BUILT_PRODUCTS_DIR}/CommonCrypto.framework" if [ -d "${FRAMEWORK_DIR}" ]; then echo "${FRAMEWORK_DIR} already exists, so skipping the rest of the script." exit 0 fi mkdir -p "${FRAMEWORK_DIR}/Modules" cat <<EOF > "${FRAMEWORK_DIR}/Modules/module.modulemap" module CommonCrypto [system] { header "${SDKROOT}/usr/include/CommonCrypto/CommonCrypto.h" export * } EOF ln -sf "${SDKROOT}/usr/include/CommonCrypto" "${FRAMEWORK_DIR}/Headers"
Этот скрипт создает базовую структуру с файлом module.map в нужном месте, а затем полагается на автоматический поиск Xcode
BUILT_PRODUCTS_DIR
фреймворков.Я связал исходную папку CommonCrypto include с папкой заголовков фреймворка, поэтому результат также должен работать для проектов Objective C.
источник
Для тех, кто использует swift 4.2 с Xcode 10 :
Модуль CommonCrypto теперь предоставляется системой, поэтому вы можете напрямую импортировать его, как и любую другую системную структуру.
import CommonCrypto
источник
@mogstad любезно обернул раствор @stephencelis в Cocoapod:
под "libCommonCrypto"
Другие доступные модули мне не подошли.
источник
Решения modulemap могут быть хорошими и устойчивыми к изменениям SDK, но я считаю их неудобными для использования на практике и не такими надежными, как хотелось бы, при передаче вещей другим. Чтобы попытаться сделать все более надежным, я пошел другим путем:
Просто скопируйте заголовки.
Я знаю, хрупкая. Но Apple почти никогда не вносит существенных изменений в CommonCrypto, и я живу мечтой, что они не изменят его каким-либо существенным образом, не сделав, наконец, CommonCrypto модульным заголовком.
Под «копированием заголовков» я подразумеваю «вырезать и вставить все нужные заголовки в один массивный заголовок в вашем проекте, как это сделал бы препроцессор». В качестве примера этого, который вы можете скопировать или адаптировать, см. RNCryptor.h .
Обратите внимание, что все эти файлы лицензированы в соответствии с APSL 2.0, и этот подход намеренно поддерживает уведомления об авторских правах и лицензии. Мой этап конкатенации лицензирован MIT, и это применимо только до следующего уведомления о лицензии).
Я не говорю, что это красивое решение, но до сих пор это было невероятно простое решение как для реализации, так и для поддержки.
источник
Security.framework
автоматически связывается (прошло немного времени с тех пор, как я начал новый проект). Если вы получаете ошибки, это фреймворк для ссылки.Я знаю, что это старый вопрос. Но я выясняю альтернативный способ использования библиотеки в проекте 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 }
А затем в заголовке моста objective-c добавьте это
#import "NSData+NSDataEncryptionExtension.h"
А затем в классе Swift сделайте то же самое:
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 } }
Работает как положено.
источник
NSData+NSDataEncryptionExtension.h
не обязательно публично).Я добавил немного магии cocoapods в ответ jjrscott на случай, если вам нужно использовать CommonCrypto в своей библиотеке cocoapods.
1) Добавьте эту строку в свой podspec:
s.script_phase = { :name => 'CommonCrypto', :script => 'sh $PROJECT_DIR/../../install_common_crypto.sh', :execution_position => :before_compile }
2) Сохраните это в папке вашей библиотеки или где угодно (однако не забудьте соответствующим образом изменить script_phase ...)
# This if-statement means we'll only run the main script if the # CommonCrypto.framework 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 FRAMEWORK_DIR="${BUILT_PRODUCTS_DIR}/CommonCrypto.framework" if [ -d "${FRAMEWORK_DIR}" ]; then echo "${FRAMEWORK_DIR} already exists, so skipping the rest of the script." exit 0 fi mkdir -p "${FRAMEWORK_DIR}/Modules" echo "module CommonCrypto [system] { header "${SDKROOT}/usr/include/CommonCrypto/CommonCrypto.h" export * }" >> "${FRAMEWORK_DIR}/Modules/module.modulemap" ln -sf "${SDKROOT}/usr/include/CommonCrypto" "${FRAMEWORK_DIR}/Headers"
Работает как шарм :)
источник
CommonCrypto
. Следует ли мне исправить свой модуль или его следует исправить в этом модуле стороннего производителя?Я не уверен, что в Xcode 9.2 что-то изменилось, но теперь добиться этого стало намного проще. Единственное, что мне нужно было сделать, это создать папку с именем «CommonCrypto» в каталоге моего фреймворка и создать в ней два файла, один из которых называется «cc.h», как показано ниже:
#include <CommonCrypto/CommonCrypto.h> #include <CommonCrypto/CommonRandom.h>
И еще один под названием module.modulemap:
module CommonCrypto { export * header "cc.h" }
(Я не знаю, почему вы не можете ссылаться на файлы заголовков из области SDKROOT непосредственно в файле modulemap, но мне не удалось заставить его работать)
В-третьих, найдите параметр «Импорт путей» и установите значение $ (SRCROOT). Фактически, вы можете установить его в любую папку, в которой должна находиться папка CommonCrypto, если вы не хотите, чтобы она находилась на корневом уровне.
После этого вы сможете использовать
import CommonCrypto
В любом swift файле и во всех типах / функциях / и т.д. доступны.
Небольшое предупреждение: если ваше приложение использует libCommonCrypto (или libcoreCrypto), не слишком опытному хакеру будет очень легко присоединить отладчик к вашему приложению и узнать, какие ключи передаются этим функциям.
источник
Если у вас возникла следующая проблема:
В Xcode 10 Swift 4.0. CommonCrypto является частью фреймворка.
Добавить
import CommonCrypto
удалять
import CommonCrypto
из заголовка мостаЭто сработало для меня!
источник
То же произошло и со мной после обновления Xcode. Я пробовал все, что мог, например, переустанавливать cocoapods и очищать проект, но это не сработало. Теперь это решено после перезагрузки системы.
источник
Все очень просто. Добавить
#import <CommonCrypto/CommonCrypto.h>
в файл .h (файл заголовка моста вашего проекта). По соглашению вы можете называть его YourProjectName-Bridging-Header.h.
Затем перейдите в настройки сборки проекта и найдите Swift Compiler - Code Generation. Под ним добавьте имя заголовка моста к записи «Заголовок моста Objetive-C».
Готово. В вашем коде Swift импорт не требуется. Любые общедоступные заголовки Objective-C, перечисленные в этом файле заголовка моста, будут видны Swift.
источник