ios - एक स्विफ्ट ढांचे में CommonCrypto आयात




swift (8)

@ मोगास्टेड कोकोपोड में @ स्टफेनसेलिस समाधान को लपेटने के लिए काफी दयालु रहा है:

पॉड 'libCommonCrypto'

उपलब्ध अन्य फली मेरे लिए काम नहीं करते थे।

आईओएस के लिए स्विफ्ट फ्रेमवर्क में आप कॉमनक्रिप्टो कैसे आयात करते हैं?

मैं समझता हूं कि एक स्विफ्ट ऐप में कॉमनक्रिप्टो का उपयोग कैसे करें: आप ब्रिजिंग हेडर पर #import <CommonCrypto/CommonCrypto.h>

हालांकि, स्विफ्ट ढांचे ब्रिजिंग हेडर का समर्थन नहीं करते हैं। documentation कहता है:

आप बाहरी ढांचे को आयात कर सकते हैं जिनमें शुद्ध उद्देश्य-सी कोडबेस, शुद्ध स्विफ्ट कोडबेस, या मिश्रित भाषा कोडबेस है। बाहरी ढांचे को आयात करने की प्रक्रिया समान है कि ढांचा एक ही भाषा में लिखा गया है या दोनों भाषाओं की फाइलें हैं। जब आप बाहरी ढांचे को आयात करते हैं, तो सुनिश्चित करें कि आपके द्वारा आयात किए जा रहे ढांचे के लिए परिभाषित मॉड्यूल बिल्ड सेटिंग हां पर सेट है।

आप निम्न वाक्यविन्यास का उपयोग कर किसी भिन्न लक्ष्य के भीतर किसी भी स्विफ्ट फ़ाइल में एक ढांचा आयात कर सकते हैं:

import FrameworkName

दुर्भाग्यवश, आयात CommonCrypto काम नहीं करता है। न तो छाता शीर्षलेख पर #import <CommonCrypto/CommonCrypto.h> जोड़ना भी जोड़ता है।


Modulemap समाधान अच्छे हो सकते हैं, और एसडीके परिवर्तनों के खिलाफ मजबूत हैं, लेकिन मैंने अभ्यास में उपयोग करने के लिए उन्हें अजीब पाया है, और जितना विश्वसनीय नहीं है उतना विश्वसनीय है जितना कि मैं दूसरों को चीजों को सौंपना चाहता हूं। इसे और अधिक मूर्ख बनाने की कोशिश करने के लिए, मैं एक अलग तरीका चला गया:

बस हेडर की प्रतिलिपि बनाएँ।

मुझे पता है, नाजुक। लेकिन ऐप्पल लगभग कभी भी कॉमनक्रिप्टो में महत्वपूर्ण बदलाव नहीं करता है और मैं सपना देख रहा हूं कि वे इसे किसी भी महत्वपूर्ण तरीके से नहीं बदलेंगे, अंततः कॉमनक्रिप्टो को मॉड्यूलर हेडर बनाने के बिना भी।

"हेडर की प्रतिलिपि बनाएँ" मेरा मतलब है "प्रीप्रोसेसर की तरह ही आपके प्रोजेक्ट में एक बड़े हेडर में आपको आवश्यक सभी शीर्षकों को काटकर पेस्ट करें।" इसका एक उदाहरण के रूप में आप कॉपी या अनुकूलित कर सकते हैं, RNCryptor.h देखें।

ध्यान दें कि इन सभी फ़ाइलों को एपीएसएल 2.0 के तहत लाइसेंस प्राप्त है, और यह दृष्टिकोण जानबूझकर कॉपीराइट और लाइसेंस नोटिस को बनाए रखता है। मेरा समापन चरण एमआईटी के तहत लाइसेंस प्राप्त है, और यह केवल अगले लाइसेंस नोटिस पर लागू होता है)।

मैं यह नहीं कह रहा हूं कि यह एक सुंदर समाधान है, लेकिन अब तक यह लागू करने और समर्थन दोनों के लिए एक अविश्वसनीय रूप से सरल समाधान रहा है।


मुझे एक गिटहब प्रोजेक्ट मिला जो स्विफ्ट फ्रेमवर्क में सफलतापूर्वक कॉमनक्रिप्टो का उपयोग करता है: SHA256-Swift । साथ ही, sqlite3 के साथ एक ही समस्या के बारे में यह आलेख उपयोगी था।

उपर्युक्त के आधार पर, चरण हैं:

1) परियोजना निर्देशिका के अंदर एक CommonCrypto निर्देशिका बनाएँ। अंदर, module.map फ़ाइल बनाएं। मॉड्यूल मानचित्र हमें स्विफ्ट के भीतर मॉड्यूल के रूप में कॉमनक्रिप्टो लाइब्रेरी का उपयोग करने की अनुमति देगा। इसकी सामग्री हैं:

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) बिल्ड सेटिंग्स में, स्विफ्ट कंपाइलर के भीतर - खोज पथ , पथ आयात करने के लिए CommonCrypto निर्देशिका जोड़ें ( SWIFT_INCLUDE_PATHS )।

3) अंत में, किसी भी अन्य मॉड्यूल के रूप में अपनी स्विफ्ट फ़ाइलों के अंदर CommonCrypto आयात करें। उदाहरण के लिए:

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 सेट करना) दोहराना एक कामकाज है।

मॉड्यूल नक्शा मंच स्वतंत्र नहीं है (वर्तमान में यह एक विशिष्ट मंच, आईओएस 8 सिम्युलेटर को इंगित करता है)। मुझे नहीं पता कि मौजूदा प्लेटफॉर्म के सापेक्ष हेडर पथ कैसे बनाया जाए।

आईओएस 8 के लिए अपडेट <= हमें सफल संकलन प्राप्त करने के लिए लाइन लिंक "कॉमनक्रिप्टो" को हटा देना चाहिए।

अद्यतन / संपादित करें

मैं निम्नलिखित बिल्ड त्रुटि प्राप्त कर रहा था:

ld: लाइब्रेरी नहीं मिली- lCommonCrypto आर्किटेक्चर x86_64 क्लैंग के लिए: त्रुटि: लिंकर कमांड निकास कोड 1 के साथ विफल रहा (उपयोग -v को देखने के लिए उपयोग करें)

जब तक मैंने module.map फ़ाइल से लाइन link "CommonCrypto" को हटा नहीं दिया। एक बार जब मैंने इस लाइन को हटा दिया तो यह ठीक हो गया।


मुझे पता है कि यह एक पुराना सवाल है। लेकिन मुझे स्विफ्ट प्रोजेक्ट में लाइब्रेरी का उपयोग करने का एक वैकल्पिक तरीका पता है, जो उन लोगों के लिए उपयोगी हो सकता है जो इन उत्तरों में पेश किए गए ढांचे को आयात नहीं करना चाहते हैं।

स्विफ्ट प्रोजेक्ट में, ऑब्जेक्टिव-सी ब्रिजिंग हेडर बनाएं, उद्देश्य-सी में एनएसडीटा श्रेणी (या लाइब्रेरी का उपयोग करने के लिए कस्टम क्लास) बनाएं। एकमात्र कमी यह होगी कि आपको उद्देश्य-सी में सभी कार्यान्वयन कोड लिखना होगा। उदाहरण के लिए:

#import "NSData+NSDataEncryptionExtension.h"
#import <CommonCrypto/CommonCryptor.h>

@implementation NSData (NSDataEncryptionExtension)
- (NSData *)AES256EncryptWithKey:(NSString *)key {
    //do something
}

- (NSData *)AES256DecryptWithKey:(NSString *)key {
//do something
}

और फिर अपने उद्देश्य-सी ब्रिजिंग हेडर में, इसे जोड़ें

#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
}
}

यह उम्मीद के रूप में काम करता है।


मॉड्यूल मैप स्वचालित रूप से और सही एक्सकोड / एसडीके पथ के साथ उत्पन्न करने के लिए एक रन स्क्रिप्ट चरण के साथ "CommonCryptoModuleMap" नामक कुल लक्ष्य बनाने के लिए थोड़ा सा सरल और अधिक मजबूत है:

रन स्क्रिप्ट चरण में इस बैश होना चाहिए:

# 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 का उपयोग करते हैं, या एक पर निर्माण कर रहे हैं सीआई सर्वर जहां गैर मानक स्थानों में एकाधिक संस्करण स्थापित हैं। आपको एसडीके को कड़ी कोड करने की भी आवश्यकता नहीं है, इसलिए इसे आईओएस, मैकोज़ आदि के लिए काम करना चाहिए। आपको अपनी परियोजना की स्रोत निर्देशिका में बैठे कुछ भी करने की आवश्यकता नहीं है।

इस लक्ष्य को बनाने के बाद, अपनी लाइब्रेरी / ढांचे को लक्षित निर्भरता आइटम के साथ उस पर निर्भर करें:

यह सुनिश्चित करेगा कि आपके ढांचे के निर्माण से पहले मॉड्यूल मानचित्र उत्पन्न होता है।

मैकोज़ नोट : यदि आप macOS समर्थन कर रहे हैं, तो आपको बनाए गए नए समेकित लक्ष्य पर Supported Platforms macosx सेटिंग में macosx जोड़ने की आवश्यकता होगी, अन्यथा यह मॉड्यूल मानचित्र को सही Debug व्युत्पन्न डेटा फ़ोल्डर में नहीं रखेगा ढांचे के बाकी उत्पादों के साथ।

इसके बाद, स्विफ्ट अनुभाग ( SWIFT_INCLUDE_PATHS ) के तहत "आयात पथ" निर्माण सेटिंग में मॉड्यूल मानचित्र की मूल निर्देशिका, ${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMap SWIFT_INCLUDE_PATHS :

यदि आपके पास प्रोजेक्ट या xcconfig स्तर पर परिभाषित खोज पथ हैं, तो $(inherited) लाइन जोड़ने के लिए याद रखें।

यही है, अब आप import CommonCrypto करने में सक्षम होना चाहिए


यदि हैशिंग एल्गोरिदम के लिए यहां हैं, जैसे SHA, MD5 आदि, भारी कॉमनक्रिप्टो लाइब्रेरी का उपयोग न करें। उस विशिष्ट हैशिंग लाइब्रेरी को ढूंढें जिसे आप ढूंढ रहे हैं।

उदाहरण के लिए, एमडी 5 के लिए, आप SwiftHash साथ जा सकते हैं


यह बहुत सरल है। जोड़ना

#import <CommonCrypto/CommonCrypto.h>

एक .h फ़ाइल (आपके प्रोजेक्ट की ब्रिजिंग हेडर फ़ाइल) में। एक सम्मेलन के रूप में आप इसे अपने प्रोजेक्टनाम-ब्रिजिंग-हेडर.h कह सकते हैं।

फिर अपनी परियोजना बिल्ड सेटिंग्स पर जाएं और स्विफ्ट कंपाइलर - कोड जनरेशन देखें। इसके तहत, "ब्रिजिंग-सी ब्रिजिंग हैडर" प्रविष्टि में अपने ब्रिजिंग हेडर का नाम जोड़ें।

हो गया। आपके स्विफ्ट कोड में कोई आयात आवश्यक नहीं है। इस ब्रिजिंग हेडर फ़ाइल में सूचीबद्ध कोई भी सार्वजनिक उद्देश्य-सी शीर्षलेख स्विफ्ट के लिए दृश्यमान होगा।


चेतावनी: iTunesConnect इस विधि का उपयोग कर रहे ऐप्स को reject सकता है।

मेरी टीम के नए सदस्य ने गलती से शीर्ष उत्तरों में से एक द्वारा दिए गए समाधान को तोड़ दिया, इसलिए मैंने इसे CommonCryptoModule नामक एक छोटी रैपर परियोजना में समेकित करने का निर्णय लिया। आप इसे मैन्युअल रूप से या कोकोपोड के माध्यम से इंस्टॉल कर सकते हैं:

pod 'CommonCryptoModule', '~> 1.0.2'

फिर, आपको बस इतना करना है कि मॉड्यूल को आयात करना जहां आपको CommonCrypto आवश्यकता है, जैसे:

import CommonCryptoModule

आशा है कि किसी और को यह उपयोगी लगेगा।





commoncrypto