Jak importować CommonCrypto
w środowisku Swift na iOS?
Rozumiem, jak używać CommonCrypto
w aplikacji Swift: dodajesz #import <CommonCrypto/CommonCrypto.h>
do nagłówka pomostowego. Jednak frameworki Swift nie obsługują mostkowania nagłówków. Dokumentacja mówi:
Możesz importować zewnętrzne frameworki, które mają czystą bazę kodową Objective-C, czystą bazę kodową Swift lub bazę kodową w języku mieszanym. Proces importowania zewnętrznego frameworka jest taki sam, niezależnie od tego, czy frameworku jest napisany w jednym języku, czy zawiera pliki z obu języków. Podczas importowania frameworka zewnętrznego upewnij się, że ustawienie kompilacji modułu Definiuje dla importowanej frameworku jest ustawione na Tak.
Możesz zaimportować strukturę do dowolnego pliku Swift w innym celu za pomocą następującej składni:
import FrameworkName
Niestety import CommonCrypto
nie działa. Nie dodaje się również #import <CommonCrypto/CommonCrypto.h>
do nagłówka parasola.
źródło
Odpowiedzi:
Coś nieco prostszego i bardziej niezawodnego polega na utworzeniu celu agregującego o nazwie „CommonCryptoModuleMap” z fazą Run Script w celu automatycznego wygenerowania mapy modułów i prawidłowej ścieżki Xcode / SDK:
Faza Uruchom skrypt powinna zawierać ten bash:
Używanie kodu powłoki i
${SDKROOT}
oznacza, że nie musisz kodować na stałe ścieżki Xcode.app, która może różnić się w zależności od systemu, szczególnie jeśli używaszxcode-select
do przejścia do wersji beta lub budujesz na serwerze CI, na którym zainstalowanych jest wiele wersji w niestandardowych lokalizacjach. Nie musisz też kodować na stałe SDK, więc powinno to działać na iOS, macOS itp. Nie musisz też mieć niczego, co mogłoby znajdować się w katalogu źródłowym twojego projektu.Po utworzeniu tego celu uzależnij swoją bibliotekę / strukturę za pomocą elementu Zależności docelowe:
Zapewni to wygenerowanie mapy modułów przed zbudowaniem frameworka.
Uwaga dotycząca systemu macOS : jeśli również wspierasz
macOS
, musisz dodaćmacosx
doSupported Platforms
ustawienia kompilacji nowego właśnie utworzonego celu zagregowanego, inaczej nie umieści on mapy modułów w odpowiednimDebug
folderze danych pochodnych wraz z resztą produkty ramowe.Następnie dodaj katalog nadrzędny mapy modułów
${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap
do ustawienia kompilacji „Importuj ścieżki” w sekcji Swift (SWIFT_INCLUDE_PATHS
):Pamiętaj, aby dodać
$(inherited)
wiersz, jeśli masz ścieżki wyszukiwania zdefiniowane na poziomie projektu lub xcconfig.To wszystko, powinieneś teraz być w stanie
import CommonCrypto
Zaktualizuj Xcode 10
Xcode 10 jest teraz dostarczany z mapą modułów CommonCrypto, dzięki czemu to obejście nie jest konieczne. Jeśli chcesz obsługiwać zarówno Xcode 9, jak i 10, możesz sprawdzić w fazie Run Script, czy mapa modułu istnieje, czy nie, np.
źródło
Możesz faktycznie zbudować rozwiązanie, które „po prostu działa” (nie musisz kopiować modułu.modulemap i
SWIFT_INCLUDE_PATHS
ustawień do projektu, jak wymagają tego inne rozwiązania tutaj), ale wymaga to stworzenia fałszywego frameworka / modułu, który „ Zaimportuję do twojego frameworka. Możemy również zapewnić, że działa niezależnie od platformy (iphoneos
,iphonesimulator
lubmacosx
).Dodaj nowy cel struktury do projektu i nazwij go po bibliotece systemowej, np. „CommonCrypto”. (Możesz usunąć nagłówek parasola CommonCrypto.h .)
Dodaj nowy plik ustawień konfiguracji i nazwij go, np. „CommonCrypto.xcconfig”. (Nie zaznaczaj żadnego z celów pod kątem włączenia.) Wypełnij go następującymi danymi:
Utwórz trzy wyżej wymienione pliki map modułów i wypełnij je następującymi elementami:
iphoneos.modulemap
iphonesimulator.modulemap
macosx.modulemap
(Jeśli używasz wersji beta, zamień „Xcode.app” na „Xcode-beta.app”. Zastąp
10.11
obecny pakiet SDK systemu operacyjnego, jeśli nie używasz El Capitan.)Na Info zakładce ustawień projektu, pod Konfiguracje ustaw Debug i Release konfiguracje CommonCrypto do CommonCrypto (odwołującego CommonCrypto.xcconfig ).
Na karcie Fazy kompilacji celu struktury szkieletowej dodaj strukturę CommonCrypto do Zależności docelowych . Dodatkowo dodaj libcommonCrypto.dylib do fazy kompilacji Link Binary With Libraries .
Wybierz CommonCrypto.framework w produktach i upewnij się, że jego docelowe członkostwo dla opakowania jest ustawione na opcjonalne .
Powinieneś być teraz w stanie budować, uruchamiać i
import CommonCrypto
w swoim środowisku opakowującym.Na przykład zobacz, jak SQLite.swift używa fałszywego narzędzia sqlite3.framework .
źródło
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
. Warto zauważyć, że jeśli twoja platforma jest wieloplatformowa, musisz stworzyć oddzielną strukturę opakowania dla komputerów Mac i iOS.Znalazłem projekt GitHub, który z powodzeniem wykorzystuje CommonCrypto w środowisku Swift: SHA256-Swift . Przydał się także ten artykuł o tym samym problemie z sqlite3 .
W oparciu o powyższe kroki są następujące:
1) Utwórz
CommonCrypto
katalog w katalogu projektu. Wewnątrz utwórzmodule.map
plik. Mapa modułów pozwoli nam korzystać z biblioteki CommonCrypto jako modułu w Swift. Jego zawartość to:2) W Ustawieniach kompilacji, w Swift Compiler - Search Paths , dodaj
CommonCrypto
katalog do Importuj ścieżki (SWIFT_INCLUDE_PATHS
).3) Na koniec zaimportuj CommonCrypto do plików Swift, tak jak inne moduły. Na przykład:
Ograniczenia
Użycie niestandardowej struktury w innym projekcie kończy się niepowodzeniem podczas kompilacji z błędem
missing required module 'CommonCrypto'
. Wynika to z faktu, że moduł CommonCrypto nie wydaje się być dołączany do niestandardowej struktury. Obejściem tego problemu jest powtórzenie kroku 2 (ustawienieImport Paths
) w projekcie korzystającym z frameworka.Mapa modułów nie jest niezależna od platformy (obecnie wskazuje na konkretną platformę, symulator iOS 8). Nie wiem, jak ustawić ścieżkę nagłówka względem bieżącej platformy.
Aktualizacje dla iOS 8 <= Powinniśmy usunąć link do linii „CommonCrypto” , aby uzyskać udaną kompilację.
AKTUALIZACJA / EDYCJA
Wciąż pojawiał się następujący błąd kompilacji:
Chyba że usunąłem linię
link "CommonCrypto"
z utworzonegomodule.map
pliku. Kiedy usunąłem tę linię, zbudowała się dobrze.źródło
$SDKROOT
zmienna ma umożliwić ci agnostyczne ścieżki platformy, ale nie mam pojęcia, jak się do tego dostać w Swift.link "CommonCrypto"
pliku module.map.Ta odpowiedź omawia, jak sprawić, by działał wewnątrz frameworka oraz w Cocoapods i Carthage
Approach podejście modulemap
Używam
modulemap
w swoim opakowaniu wokół CommonCrypto https://github.com/onmyway133/arcane , https://github.com/onmyway133/ReindeerDla tych
header not found
, którzy dostają , spójrz https://github.com/onmyway133/Arcane/issues/4 lub uruchomxcode-select --install
Utwórz folder
CCommonCrypto
zawierającymodule.modulemap
Przejdź do Ustawień wbudowanych -> Importuj ścieżki
🌳 Cocoapods z podejściem modulemap
Oto https://github.com/onmyway133/Arcane/blob/master/Arcane.podspec
Korzystanie
module_map
nie działa, patrz https://github.com/CocoaPods/CocoaPods/issues/5271Korzystanie z narzędzia Local Development Pod
path
nie działa, patrz https://github.com/CocoaPods/CocoaPods/issues/809Właśnie dlatego widzisz, że mój przykład Podfile https://github.com/onmyway133/CommonCrypto.swift/blob/master/Example/CommonCryptoSwiftDemo/Podfile wskazuje na repozytorium git
Approach podejście do nagłówka publicznego
Ji jest opakowaniem wokół libxml2 i wykorzystuje publiczne podejście do nagłówków
Ma plik nagłówka https://github.com/honghaoz/Ji/blob/master/Source/Ji.h z
Target Membership
ustawionym naPublic
Posiada listę plików nagłówkowych dla libxml2 https://github.com/honghaoz/Ji/tree/master/Source/Ji-libxml
Ma Ustawienia kompilacji -> Ścieżki wyszukiwania nagłówka
Ma Ustawienia kompilacji -> Inne flagi linkera
🐏 Cocoapods z publicznym podejściem do nagłówka
Spójrz na podspec https://github.com/honghaoz/Ji/blob/master/Ji.podspec
🐝 Ciekawe powiązane posty
źródło
/CommonCrypto/CommonCrypto.h
wewnątrzApplications/XCode.app/Contents/Developer/Platforms/iPhoneOS....
, co wymagało ręcznej modyfikacji dla osób, które zmieniły nazwę XCode. Zmiana tej linii, aby spojrzeć,"/usr/include/CommonCrypto/CommonCrypto.h"
wydaje się działać dobrze dla zespołu z kilkoma wersjami XCode. Dziękuję bardzo!pod lib lint
, ale kompilacja nie powiodła się z błędem: nie ma takiego modułu „CommonCrypto”. Jak sobie z tym poradzić.$(PODS_ROOT)/CommonCryptoSwift/Sources/CCommonCrypto
się$(PODS_TARGET_SRCROOT)/Sources/CCommonCrypto
.PODS_TARGET_SRCROOT
jest ustawiony poprawnie dla lokalnych zasobników.Dobre wieści! Swift 4.2 (Xcode 10) wreszcie udostępnia CommonCrypto!
Po prostu dodaj
import CommonCrypto
swój szybki plik.źródło
CommonCrypto
moduły, dlatego podejrzewałem, że Apple pod warunkiem, że usuną moje obejście i lo! To była prawda. Napisałem o tym na Twitterze i inżynier Apple odpowiedział, że jest zamierzony.OSTRZEŻENIE: iTunesConnect może odrzucać aplikacje korzystające z tej metody.
Nowy członek mojego zespołu przypadkowo złamał rozwiązanie podane przez jedną z najlepszych odpowiedzi, więc postanowiłem skonsolidować je w małym projekcie opakowania o nazwie CommonCryptoModule . Możesz zainstalować go ręcznie lub za pośrednictwem Cocoapods:
Następnie wystarczy zaimportować moduł tam, gdzie jest potrzebny
CommonCrypto
, w następujący sposób:Mam nadzieję, że ktoś inny uzna to za przydatne.
źródło
Myślę, że poprawiłem doskonałą pracę Mike'a Wellera.
Dodaj fazę Run Script przed
Compile Sources
fazą zawierającą ten bash:Ten skrypt konstruuje szkielet gołej kości z modułem module.map we właściwym miejscu, a następnie polega na automatycznym wyszukiwaniu
BUILT_PRODUCTS_DIR
ramek przez Xcode .Połączyłem oryginalny folder dołączania CommonCrypto jako folder nagłówków frameworka, więc wynik powinien również działać w projektach Celu C.
źródło
Dla każdego używającego swift 4.2 z Xcode 10 :
Moduł CommonCrypto jest teraz dostarczany przez system, więc możesz go zaimportować bezpośrednio, tak jak każdą inną strukturę systemu.
źródło
@mogstad był na tyle miły, że umieścił rozwiązanie @stephencelis w Cocoapod:
pod „libCommonCrypto”
Inne dostępne kapsułki nie działały dla mnie.
źródło
Rozwiązania z modulemapami mogą być dobre i odporne na zmiany SDK, ale okazało się, że są one niewygodne w użyciu i nie są tak niezawodne, jak bym chciał, gdy przekazuję je innym. Aby uczynić to bardziej niezawodnym, poszedłem inną drogą:
Po prostu skopiuj nagłówki.
Wiem, kruche. Ale Apple prawie nigdy nie wprowadza znaczących zmian w CommonCrypto i żyję marzeniem, że nie zmienią go w żaden znaczący sposób bez ostatecznego przekształcenia CommonCrypto w modułowy nagłówek.
Przez „skopiuj nagłówki” mam na myśli „wytnij i wklej wszystkie potrzebne nagłówki do jednego ogromnego nagłówka w swoim projekcie, tak jak zrobiłby to preprocesor”. Jako przykład tego można skopiować lub dostosować, patrz RNCryptor.h .
Należy pamiętać, że wszystkie te pliki są objęte licencją APSL 2.0, a to podejście celowo utrzymuje prawa autorskie i uwagi dotyczące licencji. Mój krok konkatenacji jest licencjonowany na podstawie MIT, a dotyczy to tylko następnego zawiadomienia o licencji).
Nie twierdzę, że jest to piękne rozwiązanie, ale jak dotąd wydaje się, że było to niezwykle proste rozwiązanie zarówno dla wdrożenia, jak i wsparcia.
źródło
Security.framework
jest automatycznie łączony (minęło trochę czasu od rozpoczęcia nowego projektu). Jeśli pojawią się błędy, jest to struktura do połączenia.Wiem, że to stare pytanie. Ale wymyślam alternatywny sposób korzystania z biblioteki w projekcie Swift, który może być pomocny dla tych, którzy nie chcą importować frameworku przedstawionego w tych odpowiedziach.
W projekcie Swift utwórz nagłówek mostkujący Objective-C, stwórz kategorię NSData (lub klasę niestandardową, która ma korzystać z biblioteki) w Objective-C. Jedyną wadą byłoby to, że musisz napisać cały kod implementacji w Objective-C. Na przykład:
A następnie w nagłówku mostkowania celu c dodaj to
A potem w klasie Swift wykonaj podobne rzeczy:
Działa zgodnie z oczekiwaniami.
źródło
NSData+NSDataEncryptionExtension.h
nie muszą być publiczne).Dodałem trochę magii cocoapods do odpowiedzi jjrscotta na wypadek, gdybyś musiał użyć CommonCrypto w swojej bibliotece cocoapods.
1) Dodaj tę linię do swojego podspec:
2) Zapisz to w folderze biblioteki lub gdziekolwiek chcesz (nie zapomnij jednak odpowiednio zmienić fazy skryptu ...)
Działa jak marzenie :)
źródło
Nie jestem pewien, czy coś się zmieniło w Xcode 9.2, ale teraz jest o wiele łatwiej to osiągnąć. Jedyne, co musiałem zrobić, to utworzyć folder o nazwie „CommonCrypto” w moim katalogu projektu frameworka i utworzyć w nim dwa pliki, jeden o nazwie „cc.h” w następujący sposób:
I kolejny o nazwie module.modulemap:
(Nie wiem, dlaczego nie można odwoływać się do plików nagłówkowych z obszaru SDKROOT bezpośrednio w pliku modulemap, ale nie mogłem go uruchomić)
Trzecią rzeczą jest znalezienie ustawienia „Importuj ścieżki” i ustawienie na $ (SRCROOT). W rzeczywistości możesz ustawić go na dowolny folder, w którym ma znajdować się folder CommonCrypto, jeśli nie chcesz go na poziomie głównym.
Po tym powinieneś być w stanie korzystać
W dowolnym szybkim pliku i wszystkich typach / funkcjach / itp. są dostępne.
Słowo ostrzeżenia - jeśli Twoja aplikacja korzysta z libCommonCrypto (lub libcoreCrypto) wyjątkowo niezbyt wyrafinowanemu hakerowi wyjątkowo łatwo jest podłączyć debugera do Twojej aplikacji i dowiedzieć się, jakie klucze są przekazywane do tych funkcji.
źródło
Jeśli masz następujący problem:
W Xcode 10, Swift 4.0. CommonCrypto jest częścią frameworka.
Dodaj
Usunąć
import CommonCrypto
z nagłówka BridgingTo zadziałało dla mnie!
źródło
Tak samo stało się ze mną po aktualizacji Xcode. Próbowałem wszystkiego, co mogłem zrobić, takich jak ponowna instalacja kokosów i czyszczenie projektu, ale to nie zadziałało. Teraz zostało rozwiązane po ponownym uruchomieniu systemu.
źródło
To jest bardzo proste. Dodaj
do pliku .h (mostkowy plik nagłówkowy twojego projektu). Jako konwencja możesz nazwać go YourProjectName-Bridging-Header.h.
Następnie przejdź do projektu Ustawienia budowania i poszukaj Swift Compiler - Generowanie kodu. Pod nim dodaj nazwę nagłówka pomostowego do wpisu „Objetive-C Bridging Header”.
Jesteś skończony. Nie wymaga importu w kodzie Swift. Wszelkie publiczne nagłówki Celu C wymienione w tym łączącym pliku nagłówkowym będą widoczne dla Swift.
źródło