Wie importiere ich CommonCrypto
in ein Swift-Framework für iOS?
Ich verstehe, wie man CommonCrypto
in einer Swift-App verwendet: Sie fügen #import <CommonCrypto/CommonCrypto.h>
dem Bridging-Header hinzu. Swift-Frameworks unterstützen jedoch keine Bridging-Header. Die Dokumentation sagt:
Sie können externe Frameworks importieren, die eine reine Objective-C-Codebasis, eine reine Swift-Codebasis oder eine gemischtsprachige Codebasis haben. Der Vorgang zum Importieren eines externen Frameworks ist der gleiche, unabhängig davon, ob das Framework in einer einzigen Sprache geschrieben ist oder Dateien aus beiden Sprachen enthält. Stellen Sie beim Importieren eines externen Frameworks sicher, dass die Build-Einstellung Defines Module für das zu importierende Framework auf Yes festgelegt ist.
Sie können ein Framework mit der folgenden Syntax in eine beliebige Swift-Datei innerhalb eines anderen Ziels importieren:
import FrameworkName
Leider CommonCrypto
funktioniert der Import nicht. Das Hinzufügen #import <CommonCrypto/CommonCrypto.h>
zum Umbrella-Header erfolgt ebenfalls nicht.
quelle
Antworten:
Etwas einfacher und robuster ist es, ein Aggregatziel namens "CommonCryptoModuleMap" mit einer Run Script-Phase zu erstellen, um die Modulzuordnung automatisch und mit dem richtigen Xcode / SDK-Pfad zu generieren:
Die Run Script-Phase sollte diesen Bash enthalten:
Wenn Sie Shell-Code verwenden
${SDKROOT}
, müssen Sie den Pfad Xcode.app nicht hart codieren, was von System zu System variieren kann, insbesondere wenn Siexcode-select
zu einer Beta-Version wechseln oder auf einem CI-Server aufbauen, auf dem mehrere Versionen installiert sind an nicht standardmäßigen Standorten. Sie müssen das SDK auch nicht hart codieren, damit dies für iOS, macOS usw. funktioniert. Außerdem muss sich nichts im Quellverzeichnis Ihres Projekts befinden.Stellen Sie nach dem Erstellen dieses Ziels Ihre Bibliothek / Ihr Framework mit einem Element "Zielabhängigkeiten" davon abhängig:
Dadurch wird sichergestellt, dass die Modulzuordnung generiert wird, bevor Ihr Framework erstellt wird.
macOS-Hinweis : Wenn Sie ebenfalls unterstützen
macOS
, müssen Siemacosx
dieSupported Platforms
Build-Einstellung für das neue Aggregatziel, das Sie gerade erstellt haben, erweitern, da sonst die Modulzuordnung nichtDebug
mit dem Rest des Ordners im richtigen abgeleiteten Datenordner abgelegt wird Rahmenprodukte.Fügen Sie als Nächstes das übergeordnete Verzeichnis
${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap
der Modulzuordnung zur Build-Einstellung "Pfade importieren" im Abschnitt "Swift" (SWIFT_INCLUDE_PATHS
) hinzu:Denken Sie daran, eine
$(inherited)
Zeile hinzuzufügen , wenn Sie Suchpfade auf Projekt- oder xcconfig-Ebene definiert haben.Das war's, du solltest es jetzt können
import CommonCrypto
Update für Xcode 10
Xcode 10 wird jetzt mit einer CommonCrypto-Modulzuordnung geliefert, sodass diese Problemumgehung nicht mehr erforderlich ist. Wenn Sie sowohl Xcode 9 als auch Xcode 10 unterstützen möchten, können Sie in der Phase "Skript ausführen" überprüfen, ob die Modulzuordnung vorhanden ist oder nicht, z
quelle
Sie können tatsächlich eine Lösung erstellen, die "einfach funktioniert" (Sie müssen keine module.modulemap und
SWIFT_INCLUDE_PATHS
Einstellungen in Ihr Projekt kopieren , wie dies für andere Lösungen hier erforderlich ist), aber Sie müssen ein Dummy-Framework / Modul erstellen, das Sie ' Ich importiere in Ihr Framework. Wir können auch dafür sorgen , es funktioniert unabhängig von der Plattform (iphoneos
,iphonesimulator
odermacosx
).Fügen Sie Ihrem Projekt ein neues Framework-Ziel hinzu und benennen Sie es nach der Systembibliothek, z. B. "CommonCrypto". (Sie können den Umbrella-Header CommonCrypto.h löschen .)
Fügen Sie eine neue Datei - Konfigurationseinstellungen und nennt es, zum Beispiel , „CommonCrypto.xcconfig“. (Überprüfen Sie keines Ihrer Ziele auf Aufnahme.) Füllen Sie Folgendes aus:
Erstellen Sie die drei oben genannten Modulzuordnungsdateien oben und füllen Sie sie mit den folgenden Angaben:
iphoneos.modulemap
iphonesimulator.modulemap
macosx.modulemap
(Ersetzen Sie "Xcode.app" durch "Xcode-beta.app", wenn Sie eine Beta-Version ausführen. Ersetzen Sie sie
10.11
durch Ihr aktuelles OS SDK, wenn Sie El Capitan nicht ausführen.)Setzen Sie auf der Registerkarte Info Ihrer Projekteinstellungen unter Konfigurationen die Debug- und Release- Konfigurationen von CommonCrypto auf CommonCrypto (unter Bezugnahme auf CommonCrypto.xcconfig ).
Auf dem Framework - Ziel Build - Phasen Registerkarte, fügen Sie den CommonCrypto Rahmen Ziel Abhängigkeiten . Fügen Sie außerdem libcommonCrypto.dylib zur Erstellungsphase von Link Binary With Libraries hinzu .
Wählen Sie CommonCrypto.framework in Produkten und stellen Sie sicher , dass sein Ziel Mitgliedschaft für Ihren Wrapper gesetzt ist Optional .
Sie sollten nun in der Lage sein,
import CommonCrypto
Ihr Wrapper-Framework zu erstellen, auszuführen und zu verwenden .Ein Beispiel finden Sie unter Verwendung von Dummy sqlite3.framework durch SQLite.swift .
quelle
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
erstellen. Es ist erwähnenswert, dass Sie ein separates Wrapper-Framework für Mac und iOS erstellen müssen, wenn Ihr Framework plattformübergreifend ist.Ich habe ein GitHub-Projekt gefunden, das CommonCrypto erfolgreich in einem Swift-Framework verwendet: SHA256-Swift . Auch dieser Artikel über das gleiche Problem mit sqlite3 war nützlich.
Basierend auf dem oben Gesagten sind die Schritte:
1) Erstellen Sie ein
CommonCrypto
Verzeichnis innerhalb des Projektverzeichnisses. Erstellen Sie innerhalb einemodule.map
Datei. Die Modulzuordnung ermöglicht es uns, die CommonCrypto-Bibliothek als Modul in Swift zu verwenden. Sein Inhalt ist:2) Fügen Sie in den Build-Einstellungen in Swift Compiler - Suchpfade das
CommonCrypto
Verzeichnis zu Import Paths (SWIFT_INCLUDE_PATHS
) hinzu.3) Importieren Sie abschließend CommonCrypto wie alle anderen Module in Ihre Swift-Dateien. Beispielsweise:
Einschränkungen
Die Verwendung des benutzerdefinierten Frameworks in einem anderen Projekt schlägt beim Kompilieren mit dem Fehler fehl
missing required module 'CommonCrypto'
. Dies liegt daran, dass das CommonCrypto-Modul anscheinend nicht im benutzerdefinierten Framework enthalten ist. Eine Problemumgehung besteht darin, Schritt 2 (EinstellungImport Paths
) in dem Projekt zu wiederholen , das das Framework verwendet.Die Modulzuordnung ist nicht plattformunabhängig (sie verweist derzeit auf eine bestimmte Plattform, den iOS 8 Simulator). Ich weiß nicht, wie ich den Header-Pfad relativ zur aktuellen Plattform erstellen soll.
Updates für iOS 8 <= Wir sollten den Zeilenlink "CommonCrypto" entfernen , um die erfolgreiche Kompilierung zu erhalten.
UPDATE / EDIT
Ich habe immer wieder den folgenden Build-Fehler erhalten:
Es sei denn, ich habe die Zeile
link "CommonCrypto"
aus der vonmodule.map
mir erstellten Datei entfernt. Sobald ich diese Linie entfernt habe, ist sie in Ordnung.quelle
$SDKROOT
Variable Ihnen plattformunabhängige Pfade ermöglichen soll, aber ich habe keine Ahnung, wie Sie in Swift dazu gelangen können.link "CommonCrypto"
aus der module.map-Datei entfernt habe.In dieser Antwort wird erläutert, wie es in einem Framework sowie mit Cocoapods und Carthage funktioniert
🐟 Modulemap-Ansatz
Ich verwende
modulemap
in meinem Wrapper CommonCrypto https://github.com/onmyway133/arcane , https://github.com/onmyway133/ReindeerFür diejenigen, die dies erhalten
header not found
, schauen Sie bitte unter https://github.com/onmyway133/Arcane/issues/4 nach oder führen Sie es ausxcode-select --install
Erstellen Sie einen Ordner
CCommonCrypto
mitmodule.modulemap
Gehen Sie zu Erstellungseinstellungen -> Pfade importieren
🌳 Cocoapods mit Modulemap-Ansatz
Hier ist die Podspec https://github.com/onmyway133/Arcane/blob/master/Arcane.podspec
Die Verwendung
module_map
funktioniert nicht, siehe https://github.com/CocoaPods/CocoaPods/issues/5271Die Verwendung von Local Development Pod mit
path
funktioniert nicht unter https://github.com/CocoaPods/CocoaPods/issues/809Aus diesem Grund sehen Sie, dass mein Beispiel-Podfile https://github.com/onmyway133/CommonCrypto.swift/blob/master/Example/CommonCryptoSwiftDemo/Podfile auf das Git-Repo verweist
🐘 Ansatz für öffentliche Header
Ji ist ein Wrapper um libxml2 und verwendet den Ansatz eines öffentlichen Headers
Es hat eine Header-Datei https://github.com/honghaoz/Ji/blob/master/Source/Ji.h mit
Target Membership
gesetzt aufPublic
Es enthält eine Liste der Header-Dateien für libxml2 https://github.com/honghaoz/Ji/tree/master/Source/Ji-libxml
Es hat Build-Einstellungen -> Header-Suchpfade
Es hat Build-Einstellungen -> Andere Linker-Flags
🐏 Cocoapods mit öffentlichem Header-Ansatz
Schauen Sie sich die Podspec https://github.com/honghaoz/Ji/blob/master/Ji.podspec an
🐝 Interessante verwandte Beiträge
quelle
/CommonCrypto/CommonCrypto.h
innen verwendeteApplications/XCode.app/Contents/Developer/Platforms/iPhoneOS....
, die für Personen, die XCode umbenannten, manuelle Änderungen erforderte. Das Umschalten dieser Zeile"/usr/include/CommonCrypto/CommonCrypto.h"
scheint für ein Team mit mehreren XCode-Versionen gut zu funktionieren. Ich danke dir sehr!pod lib lint
, aber die Erstellung mit Fehler fehlgeschlagen ist: Kein solches Modul 'CommonCrypto'. Wie kann ich damit umgehen?$(PODS_ROOT)/CommonCryptoSwift/Sources/CCommonCrypto
mit$(PODS_TARGET_SRCROOT)/Sources/CCommonCrypto
.PODS_TARGET_SRCROOT
ist für lokale Pods richtig eingestellt.Gute Nachrichten! Swift 4.2 (Xcode 10) bietet endlich CommonCrypto!
Fügen
import CommonCrypto
Sie einfach Ihre schnelle Datei hinzu.quelle
CommonCrypto
Module gefunden werden konnten, und Apple vermutet, dass ich meine Problemumgehung und entfernt habe 'lo! Es war wahr. Ich habe darüber getwittert und ein Apple-Ingenieur hat geantwortet, dass dies beabsichtigt ist.WARNUNG: iTunesConnect lehnt möglicherweise Apps ab, die diese Methode verwenden.
Ein neues Mitglied in meinem Team hat versehentlich die Lösung einer der wichtigsten Antworten gebrochen, und ich habe beschlossen, sie in einem kleinen Wrapper-Projekt namens CommonCryptoModule zu konsolidieren . Sie können es manuell oder über Cocoapods installieren:
Dann müssen Sie nur noch das Modul an die gewünschte Stelle importieren
CommonCrypto
:Hoffe, jemand anderes findet das nützlich.
quelle
Ich glaube, ich habe eine Verbesserung von Mike Wellers hervorragender Arbeit.
Fügen Sie vor der
Compile Sources
Phase, die diese Bash enthält, eine Run Script-Phase hinzu :Dieses Skript erstellt ein Bare-Bones-Framework mit der module.map an der richtigen Stelle und stützt sich dann auf die automatische Suche von Xcode nach
BUILT_PRODUCTS_DIR
nach Frameworks.Ich habe den ursprünglichen CommonCrypto-Include-Ordner als Header-Ordner des Frameworks verknüpft, sodass das Ergebnis auch für Objective C-Projekte funktionieren sollte.
quelle
Für alle, die Swift 4.2 mit Xcode 10 verwenden :
Das CommonCrypto-Modul wird jetzt vom System bereitgestellt, sodass Sie es wie jedes andere Systemframework direkt importieren können.
quelle
@mogstad war so freundlich, @stephencelis-Lösung in einen Cocoapod zu wickeln:
pod 'libCommonCrypto'
Die anderen verfügbaren Pods haben bei mir nicht funktioniert.
quelle
Die Modulemap-Lösungen können gut sein und sind robust gegen SDK-Änderungen, aber ich fand sie in der Praxis umständlich und nicht so zuverlässig, wie ich es gerne hätte, wenn ich Dinge an andere verteile. Um alles narrensicherer zu machen, bin ich einen anderen Weg gegangen:
Kopieren Sie einfach die Header.
Ich weiß, zerbrechlich. Aber Apple nimmt fast nie wesentliche Änderungen an CommonCrypto vor und ich lebe den Traum, dass sie es nicht wesentlich ändern werden, ohne CommonCrypto schließlich auch zu einem modularen Header zu machen.
Mit "Kopieren der Header" meine ich "Ausschneiden und Einfügen aller benötigten Header in einen massiven Header in Ihrem Projekt, genau wie es der Präprozessor tun würde." Ein Beispiel dafür, das Sie kopieren oder anpassen können, finden Sie unter RNCryptor.h .
Beachten Sie, dass alle diese Dateien unter APSL 2.0 lizenziert sind und bei diesem Ansatz die Urheberrechts- und Lizenzhinweise absichtlich beibehalten werden. Mein Verkettungsschritt ist unter MIT lizenziert und dies gilt nur bis zur nächsten Lizenzbenachrichtigung.
Ich sage nicht, dass dies eine schöne Lösung ist, aber bisher scheint es eine unglaublich einfache Lösung für die Implementierung und den Support gewesen zu sein.
quelle
Security.framework
wird automatisch verlinkt (es ist eine Weile her, seit ein neues Projekt gestartet wurde). Wenn Sie Fehler erhalten, ist dies das zu verknüpfende Framework.Ich weiß, dass dies eine alte Frage ist. Ich finde jedoch eine alternative Möglichkeit, die Bibliothek im Swift-Projekt zu verwenden, die für diejenigen hilfreich sein kann, die das in diesen Antworten eingeführte Framework nicht importieren möchten.
Erstellen Sie im Swift-Projekt einen Objective-C-Bridging-Header, erstellen Sie in Objective-C eine NSData-Kategorie (oder eine benutzerdefinierte Klasse, die die Bibliothek verwenden soll). Der einzige Nachteil wäre, dass Sie den gesamten Implementierungscode in Objective-C schreiben müssen. Beispielsweise:
Fügen Sie dies dann in Ihrem Ziel-C-Überbrückungsheader hinzu
Und dann in der Swift-Klasse machen Sie etwas Ähnliches:
Es funktioniert wie erwartet.
quelle
NSData+NSDataEncryptionExtension.h
muss nicht öffentlich sein).Ich habe jjrscotts Antwort etwas Cocoapods-Magie hinzugefügt, falls Sie CommonCrypto in Ihrer Cocoapods-Bibliothek verwenden müssen.
1) Fügen Sie diese Zeile Ihrer Podspec hinzu:
2) Speichern Sie dies in Ihrem Bibliotheksordner oder wo immer Sie möchten (vergessen Sie jedoch nicht, die script_phase entsprechend zu ändern ...)
Klappt wunderbar :)
quelle
Ich bin mir nicht sicher, ob sich mit Xcode 9.2 etwas geändert hat, aber es ist jetzt viel einfacher, dies zu erreichen. Das einzige, was ich tun musste, war, einen Ordner mit dem Namen "CommonCrypto" in meinem Framework-Projektverzeichnis zu erstellen und zwei Dateien darin zu erstellen, eine mit dem Namen "cc.h" wie folgt:
Und eine andere namens module.modulemap:
(Ich weiß nicht, warum Sie Header-Dateien aus dem SDKROOT-Bereich nicht direkt in einer Modulemap-Datei referenzieren können, aber ich konnte sie nicht zum Laufen bringen.)
Die dritte Sache ist, die Einstellung "Pfade importieren" zu finden und auf $ (SRCROOT) zu setzen. Tatsächlich können Sie es auf einen beliebigen Ordner festlegen, unter dem sich der CommonCrypto-Ordner befinden soll, wenn Sie ihn nicht auf Stammebene möchten.
Danach sollten Sie in der Lage sein, zu verwenden
In jeder schnellen Datei und allen Typen / Funktionen / etc. stehen zur Verfügung.
Ein Wort der Warnung: Wenn Ihre App libCommonCrypto (oder libcoreCrypto) verwendet, ist es für einen nicht allzu hoch entwickelten Hacker außerordentlich einfach, einen Debugger an Ihre App anzuhängen und herauszufinden, welche Schlüssel an diese Funktionen übergeben werden.
quelle
Falls Sie das folgende Problem haben:
In Xcode 10 Swift 4.0. CommonCrypto ist Teil des Frameworks.
Hinzufügen
Entfernen
import CommonCrypto
vom Bridging-HeaderDas hat bei mir funktioniert!
quelle
Das ist mir auch nach dem Update von Xcode passiert. Ich habe alles versucht, was ich tun kann, z. B. Cocoapods neu installieren und das Projekt reinigen, aber es hat nicht funktioniert. Jetzt ist es nach dem Neustart des Systems behoben .
quelle
Es ist sehr einfach. Hinzufügen
in eine .h-Datei (die Bridging-Header-Datei Ihres Projekts). Als Konvention können Sie es YourProjectName-Bridging-Header.h nennen.
Gehen Sie dann zu Ihrem Projekt Build Settings und suchen Sie nach Swift Compiler - Code Generation. Fügen Sie darunter den Namen Ihres Bridging-Headers zum Eintrag "Objetive-C Bridging Header" hinzu.
Du bist fertig. In Ihrem Swift-Code sind keine Importe erforderlich. Alle öffentlichen Objective-C-Header, die in dieser Bridging-Header-Datei aufgeführt sind, sind für Swift sichtbar.
quelle