การอิมพอร์ต CommonCrypto ในเฟรมเวิร์ก Swift


184

คุณจะนำเข้าCommonCryptoเฟรมเวิร์ก Swift สำหรับ iOS ได้อย่างไร

ฉันเข้าใจวิธีใช้CommonCryptoในแอพ Swift: คุณเพิ่ม#import <CommonCrypto/CommonCrypto.h>ไปยังส่วนหัวการเชื่อมโยง อย่างไรก็ตามกรอบการทำงานของ Swift ไม่รองรับการเชื่อมต่อส่วนหัว เอกสารพูดว่า:

คุณสามารถอิมพอร์ตเฟรมเวิร์กภายนอกที่มี Objective-C codebase แท้, Swift codebase ที่บริสุทธิ์หรือ codebase ผสมภาษา กระบวนการสำหรับการนำเข้าเฟรมเวิร์กภายนอกนั้นเหมือนกันไม่ว่าเฟรมนั้นจะถูกเขียนในภาษาเดียวหรือมีไฟล์จากทั้งสองภาษา เมื่อคุณนำเข้าเฟรมเวิร์กภายนอกตรวจสอบให้แน่ใจว่าการตั้งค่าการกำหนดโมดูลการสร้างสำหรับเฟรมเวิร์กที่คุณกำลังนำเข้าถูกตั้งค่าเป็นใช่

คุณสามารถนำเข้าเฟรมเวิร์กไปยังไฟล์ Swift ใด ๆ ภายในเป้าหมายอื่นโดยใช้ไวยากรณ์ต่อไปนี้:

import FrameworkName

น่าเสียดายที่การนำเข้าCommonCryptoใช้งานไม่ได้ ไม่เพิ่ม#import <CommonCrypto/CommonCrypto.h>ลงในส่วนหัวของร่ม


CommonCrypto เป็นเฟรมเวิร์กที่ใช้ C ไม่ใช่เฟรมเวิร์ก Objective-C
rmaddy

1
@rmaddy Objective-C คือ C superset คุณกำลังบอกว่าเราไม่สามารถใช้ CommonCrypto จาก Swift ได้หรือไม่?
hpique

4
@ rmaddy ฉันเพิ่งจัดการเพื่อให้ CommonCrypto ทำงานโดยใช้โมดูลแผนที่ ฉันจะขัดทางออกและโพสต์ในวันนี้
hpique

หากคุณพบว่ามันสะดวกสบายและสิ่งที่คุณมองหาได้ถูกนำไปใช้แล้วคุณสามารถลองCryptoSwift
Marcin

1
Apple เพิ่งเปิด CommonCrypto ที่มา บางทีเราสามารถทำให้มันทำงานได้ถ้าเรามีแหล่งที่มา
eyeballz

คำตอบ:


137

สิ่งที่เรียบง่ายและมีประสิทธิภาพมากกว่าเล็กน้อยคือการสร้างเป้าหมายรวมที่เรียกว่า "CommonCryptoModuleMap" ด้วยเฟส Run Script เพื่อสร้างแผนที่โมดูลโดยอัตโนมัติและด้วยเส้นทาง Xcode / SDK ที่ถูกต้อง:

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่

ขั้นตอนการเรียกใช้สคริปต์ควรมีการทุบตีนี้:

# 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 และอื่น ๆ คุณไม่จำเป็นต้องมีสิ่งใดที่อยู่ในไดเรกทอรีต้นทางของโครงการ

หลังจากสร้างเป้าหมายนี้แล้วให้ไลบรารี่ / กรอบงานของคุณขึ้นอยู่กับรายการอ้างอิงเป้าหมาย:

ป้อนคำอธิบายรูปภาพที่นี่

สิ่งนี้จะช่วยให้แน่ใจว่าแผนที่โมดูลถูกสร้างขึ้นก่อนที่จะสร้างกรอบงานของคุณ

macOS note : หากคุณรองรับmacOSเช่นกันคุณจะต้องเพิ่มmacosxการSupported Platformsตั้งค่าการสร้างในเป้าหมายรวมใหม่ที่คุณเพิ่งสร้างมิฉะนั้นจะไม่ทำให้แผนที่โมดูลในDebugโฟลเดอร์ข้อมูลที่ได้มาถูกต้องพร้อมกับส่วนที่เหลือของ ผลิตภัณฑ์กรอบ

ป้อนคำอธิบายรูปภาพที่นี่

ถัดไปเพิ่มไดเรกทอรีหลักของโมดูลแผนที่${BUILT_PRODUCTS_DIR}/CommonCryptoModuleMapไปยังการตั้งค่าการสร้าง "เส้นทางที่นำเข้า" ภายใต้ส่วน Swift ( SWIFT_INCLUDE_PATHS):

ป้อนคำอธิบายรูปภาพที่นี่

อย่าลืมเพิ่ม$(inherited)บรรทัดหากคุณมีเส้นทางการค้นหาที่กำหนดไว้ในโครงการหรือระดับ xcconfig

เพียงเท่านี้คุณก็ควรจะสามารถ import CommonCrypto

อัพเดทสำหรับ Xcode 10

ตอนนี้ Xcode 10 มาพร้อมกับแผนที่โมดูล CommonCrypto ทำให้ไม่จำเป็นต้องแก้ไขปัญหานี้ หากคุณต้องการสนับสนุนทั้ง Xcode 9 และ 10 คุณสามารถทำการตรวจสอบในเฟส Run Script เพื่อดูว่ามีการแมปโมดูลอยู่หรือไม่เช่น

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

8
คำตอบนี้ควรจะอยู่ด้านบน เรียบง่ายและสง่างาม
Abdullah Saeed

1
มาสายสำหรับเกมนี้ - แต่ควรเป็นคำตอบที่เลือก มันง่ายและง่ายกว่าสำหรับผู้พัฒนารายอื่นที่ทำงานในโครงการเดียวกันเพื่อดูข้อกำหนด
fatuous.logic

1
คำตอบที่ดี ขอบคุณ!
Klaus Busse

1
ถ้าฉันทำสิ่งนี้ใน. เฟรมเวิร์คของฉันฉันต้องทำแบบเดียวกันในโครงการที่ฉันรวมกรอบงานนี้ไว้ด้วยหรือไม่?
Ravi Kiran

2
@IanDundas ฉันอัปเดตโค้ดด้านบนด้วยการแก้ไขปัญหาการคอมไพล์ใหม่รวมถึงการแก้ไขสำหรับการใช้งานบน macOS
iwasrobbed

91

คุณสามารถสร้างโซลูชันที่ "เพิ่งได้ผล" (ไม่จำเป็นต้องคัดลอกmodule.modulemapและSWIFT_INCLUDE_PATHSการตั้งค่าไปยังโครงการของคุณตามที่ต้องการโดยโซลูชันอื่น ๆ ที่นี่) แต่คุณต้องสร้างกรอบ / โมดูลจำลองที่คุณต้องการ จะนำเข้าสู่กรอบงานของคุณอย่างเหมาะสม นอกจากนี้เรายังสามารถมั่นใจได้ว่าการทำงานโดยไม่คำนึงถึงแพลตฟอร์ม ( iphoneos, iphonesimulatorหรือmacosx)

  1. เพิ่มเป้าหมายเฟรมเวิร์กใหม่ให้กับโครงการของคุณและตั้งชื่อตามไลบรารีระบบเช่น "CommonCrypto" (คุณสามารถลบส่วนหัวของร่มCommonCrypto.h )

  2. เพิ่มไฟล์การตั้งค่าการกำหนดค่าใหม่และตั้งชื่อเช่น "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
  3. สร้างไฟล์แผนที่โมดูลอ้างอิงสามไฟล์ด้านบนและเติมด้วยไฟล์ต่อไปนี้:

    • 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ด้วย OS SDK ปัจจุบันของคุณหากไม่ได้ใช้ El Capitan)

  4. บนแท็บข้อมูลของการตั้งค่าโครงการของคุณภายใต้การกำหนดค่าให้ตั้งค่าการกำหนดค่าDebugและReleaseของCommonCryptoเป็นCommonCrypto (อ้างอิงCommonCrypto.xcconfig )

  5. เป้าหมายกรอบของรูปร่างเฟสแท็บเพิ่มCommonCryptoกรอบเป้าหมายอ้างอิง นอกจากนี้ให้เพิ่มlibcommonCrypto.dylibไปยังขั้นตอนการสร้างLink Binary With Libraries

  6. เลือกCommonCrypto.frameworkในผลิตภัณฑ์และให้แน่ใจว่าสมาชิกเป้าหมายสำหรับกระดาษห่อของคุณตั้งค่าตัวเลือก

ตอนนี้คุณควรจะสามารถสร้างรันและimport CommonCryptoอยู่ในกรอบของ wrapper

ตัวอย่างเช่นดูว่าSQLite.swiftใช้ dummy sqlite3.frameworkอย่างไร


4
ใช้งานได้สำหรับฉันแบบไม่มีขั้นตอน (5) กับมันฉันได้รับการสร้างข้อผิดพลาด: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
stannie

4
ยอดเยี่ยม ใช้วิธีนี้จะทำให้github.com/soffes/Cryptoฉันไม่ได้มีการเชื่อมโยงSystem.frameworkว่า เป็นที่น่าสังเกตว่าคุณต้องสร้างเฟรมเวิร์กคลุมสำหรับ Mac และ iOS หากเฟรมเวิร์กของคุณเป็นแบบข้ามแพลตฟอร์ม
Sam Soffes

32
ผู้คนค้นหาสิ่งเหล่านี้ได้ที่ไหนหรือที่ไหน?
Hola

5
เพียงโน้ตทำให้ชัดเจนว่าคุณต้องเลือก Objective-C เป็นภาษาในขั้นตอนที่ 1 นี่คือการมองข้ามอย่างง่ายดาย นอกจากนี้อาจเป็นเพราะฉันไม่มี. dylib ฉันจึงจำเป็นต้องเพิ่ม. เฟรมในขั้นตอนที่ 5
Teo Sartori

7
นี่มันช่างน่ากลัว ฉันมีสวนสัตว์ของ Xcodes แต่ละอันแตกต่างกันและมีเส้นทางที่แน่นอนไปยังส่วนหัวของสถานที่ทั้งหมดคืออ้วกเรียก มีบางอย่างผิดพลาดอย่างมากในคูเปอร์ติโนหรืออย่างน้อยกับใครก็ตามที่รับผิดชอบโมดูลโมดูลนี้
Anton Tropashko

82

ผมพบว่าโครงการ GitHub ที่ประสบความสำเร็จในการใช้ CommonCrypto ในกรอบสวิฟท์: SHA256-สวิฟท์ นอกจากนี้บทความเกี่ยวกับปัญหาเดียวกันกับ 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) ใน Build Settings ภายใน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 เสียงดังกราว: ข้อผิดพลาด: คำสั่ง linker ล้มเหลวด้วยรหัสออก 1 (ใช้ -v เพื่อดูการเรียกใช้)

ถ้าฉันไม่ลบบรรทัดlink "CommonCrypto"ออกจากmodule.mapไฟล์ที่ฉันสร้าง เมื่อฉันลบบรรทัดนี้มันก็โอเค


30
Gee, Apple แน่ใจว่าต้องการทำให้สิ่งที่ยาก มันจะฆ่าชาว Swifties เพียงเพื่อให้เรานำเข้าไฟล์ / กรอบโดยไม่ต้องผ่าน BS ทั้งหมดนี้หรือไม่?
zaph

4
นี่เป็นสิ่งที่ทำให้โมโหเพราะ$SDKROOTตัวแปรควรอนุญาตให้คุณใช้แพลตฟอร์มที่ไม่เชื่อเรื่องพระเจ้า แต่ฉันไม่รู้ว่าจะไปยังมันได้อย่างไรใน Swift
danimal

2
สำหรับฉันมันไม่ทำงานจนกว่าฉันจะลบออกlink "CommonCrypto"จากไฟล์ module.map
Teo Sartori

1
ทุกคนสามารถยืนยันการทำงานกับ Xcode 7.3 ได้ไหม โซลูชันนี้หยุดทำงานสำหรับฉันหลังจากการอัปเดต
Nikita Kukushkin

1
Correnction: ทำงานได้ดีเมื่อฉันสร้างเพื่อจำลอง แต่ล้มเหลว @ การเชื่อมโยงเมื่อฉันสร้างสำหรับอุปกรณ์ iOS 9.3 ที่มี "ld: ไลบรารี่ไม่พบสำหรับ -lCommonCrypto สำหรับสถาปัตยกรรม arm64"
Nikita Kukushkin

50

คำตอบนี้กล่าวถึงวิธีที่จะทำให้มันทำงานภายในกรอบและกับ Cocoapods และ Carthage

approach วิธีการของโมดูล

ฉันใช้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 ด้วยวิธีการของโมดูล

approach วิธีส่วนหัวสาธารณะ

  • 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 พร้อมแนวทางแบบส่วนหัวสาธารณะ

posts โพสต์ที่เกี่ยวข้องที่น่าสนใจ


1
ว้าว! ด้วยความประหลาดใจของฉันเส้นทางส่วนหัวจากวิธีการด้านบน (การสร้างไฟล์ module.modulemap) ทำงานได้ดีมากเมื่อก่อนหน้านี้ไฟล์โมดูลแมปได้ก่อให้เกิดปัญหามากมาย ฉันได้รับการดิ้นรนกับสิ่งนี้ในขณะที่ใช้ไฟล์ module.modulemap กับเส้นทางที่แน่นอนไป/CommonCrypto/CommonCrypto.hภายในApplications/XCode.app/Contents/Developer/Platforms/iPhoneOS....ซึ่งจำเป็นต้องมีการปรับเปลี่ยนด้วยตนเองสำหรับผู้ที่เปลี่ยนชื่อ XCode การสลับบรรทัดนั้นเพื่อดู"/usr/include/CommonCrypto/CommonCrypto.h"ดูเหมือนว่าจะทำงานได้ดีสำหรับทีมที่มีรุ่น XCode หลายรุ่น ขอบคุณมาก!
Natalia

3
ฉันกำลังสร้างพ็อดฉันตั้งค่า SWIFT_INCLUDE_PATHS แล้วและ keep_paths เมื่อฉันเรียกใช้pod lib lintแต่การสร้างล้มเหลวโดยมีข้อผิดพลาด: ไม่มีโมดูล 'CommonCrypto' ฉันจะจัดการกับมันอย่างไร
Klein Mioke

1
ไม่เกี่ยวข้องกับปัญหา แต่ฉันชอบใช้อีโมจิเป็นกระสุน! 😊
Fomentia

2
@ onmyway133 การใช้งานในท้องถิ่นพัฒนาฝักถ้าคุณแทนที่ด้วย$(PODS_ROOT)/CommonCryptoSwift/Sources/CCommonCrypto ตั้งค่าไว้อย่างถูกต้องสำหรับพ็อดท้องถิ่น $(PODS_TARGET_SRCROOT)/Sources/CCommonCryptoPODS_TARGET_SRCROOT
Orkhan Alikhanov

คำตอบที่ดีช่วยชีวิตฉันไว้! ขอบคุณหนึ่งล้าน
Hassan Shahbazi

45

ข่าวดี! Swift 4.2 (Xcode 10) ในที่สุดก็มอบ CommonCrypto!

เพียงเพิ่มimport CommonCryptoไฟล์ที่รวดเร็วของคุณ


ข่าวดี! คุณสามารถเพิ่มลิงค์ไปยังเอกสารประกอบได้หรือไม่?
KryštofMatěj

ฉันไม่มีลิงก์ไปยังเอกสารฉันค้นพบสิ่งนี้ในขณะที่พยายามรวบรวมโครงการที่ฉันมีหนึ่งในวิธีการแก้ปัญหาที่นี่ด้วย Xcode 10 มันบ่นว่ามันสามารถหาสองCommonCryptoโมดูลได้ดังนั้น Apple จึงสงสัยว่าตอนนี้ 'แท้จริง! มันเป็นเรื่องจริง ฉันทวีตเกี่ยวกับมันและวิศวกรของ Apple ตอบยืนยันว่ามันตั้งใจ
mxcl

1
App Store แสดงให้ฉันเห็นเพียง 9.4.7 ในการอัปเดตที่มีอยู่คุณมี Xcode 10 ได้อย่างไร
Hammad Tariq

1
มันอยู่ในช่วงเบต้าเนื่องจากการค้นหาโดย Google เล็กน้อยจะบอกคุณ
mxcl

1
@SomoyDasGupta ใช่ เพียงลบการนำเข้าก่อนหน้าและรวบรวมอีกครั้ง กล่าวอีกนัยหนึ่งคุณไม่ต้องทำตามขั้นตอนจากคำตอบ MikeWeller
COLD ICE

7

คำเตือน: iTunesConnect อาจปฏิเสธแอพที่ใช้วิธีนี้


สมาชิกใหม่ในทีมของฉันตั้งใจยากจนวิธีการแก้ปัญหาที่ได้รับจากหนึ่งในคำตอบด้านบนดังนั้นฉันตัดสินใจที่จะรวมไว้ในโครงการกระดาษห่อเล็ก ๆ ที่เรียกCommonCryptoModule คุณสามารถติดตั้งด้วยตนเองหรือผ่าน Cocoapods:

pod 'CommonCryptoModule', '~> 1.0.2'

จากนั้นสิ่งที่คุณต้องทำคือนำเข้าโมดูลที่คุณต้องการCommonCryptoเช่น:

import CommonCryptoModule

หวังว่าคนอื่นจะพบว่าสิ่งนี้มีประโยชน์


คำเตือน: ใบสมัครของคุณจะถูกปฏิเสธหากคุณใช้วิธีนี้!
Segabond

ใช่เราถูกปฏิเสธเช่นกันแปลกมากเพราะเราอัปโหลดโดยไม่มีปัญหาเป็นเวลาหลายเดือนโดยใช้วิธีนี้
Nikita Kukushkin

5

ฉันคิดว่าฉันมีการปรับปรุงการทำงานที่ยอดเยี่ยมของ Mike Weller

เพิ่มเฟส Run Script ก่อน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 ในตำแหน่งที่ถูกต้องจากนั้นอาศัยการค้นหาBUILT_PRODUCTS_DIRเฟรมเวิร์กอัตโนมัติของ Xcode

ฉันเชื่อมโยงโฟลเดอร์ CommonCrypto ดั้งเดิมไว้เป็นโฟลเดอร์ส่วนหัวของเฟรมเวิร์กดังนั้นผลลัพธ์ควรทำงานสำหรับโครงการ Objective C


ดูคำตอบของ dvdblkสำหรับการปรับปรุงที่ครอบคลุมการใช้งานใน CocoaPods
jjrscott

5

สำหรับทุกคนที่ใช้swift 4.2กับXcode 10 :

ขณะนี้โมดูล CommonCrypto มีให้โดยระบบดังนั้นคุณสามารถนำเข้าโดยตรงเหมือนเฟรมเวิร์กระบบอื่น ๆ

import CommonCrypto

คำตอบของ @ mxcl ซ้ำกัน: stackoverflow.com/a/50690346/9988514
Rainer Schwarz


4

โซลูชัน modulemap นั้นดีและทนทานต่อการเปลี่ยนแปลง SDK แต่ฉันพบว่าพวกเขาใช้งานในทางปฏิบัติได้ไม่ดีเท่าที่ควรและเชื่อถือได้ไม่ดีเท่าที่ฉันต้องการเมื่อมอบสิ่งต่างๆให้ผู้อื่น เพื่อที่จะพยายามทำให้มันเข้าใจผิดได้มากกว่านี้ฉันก็เปลี่ยนวิธี:

เพียงคัดลอกส่วนหัว

ฉันรู้ว่าเปราะบาง แต่แอปเปิ้ลแทบไม่เคยเปลี่ยนแปลง CommonCrypto อย่างมีนัยสำคัญและฉันใช้ชีวิตอยู่ในความฝันที่พวกเขาจะไม่เปลี่ยนแปลงในทางที่สำคัญโดยที่ไม่ได้ทำให้ CommonCrypto กลายเป็นส่วนหัวแบบแยกส่วน

โดย "คัดลอกส่วนหัว" ฉันหมายถึง "ตัดและวางส่วนหัวทั้งหมดที่คุณต้องการลงในส่วนหัวขนาดใหญ่หนึ่งรายการในโครงการของคุณเหมือนกับที่ตัวประมวลผลล่วงหน้าทำ" เป็นตัวอย่างของการนี้ที่คุณสามารถคัดลอกหรือปรับตัวให้ดูRNCryptor.h

โปรดทราบว่าไฟล์เหล่านี้ทั้งหมดได้รับอนุญาตภายใต้ APSL 2.0 และวิธีการนี้จะเก็บรักษาประกาศลิขสิทธิ์และใบอนุญาตไว้โดยเจตนา ขั้นตอนการต่อข้อมูลของฉันได้รับอนุญาตภายใต้ MIT และสามารถใช้ได้กับประกาศเกี่ยวกับใบอนุญาตครั้งต่อไปเท่านั้น)

ฉันไม่ได้พูดว่านี่เป็นวิธีแก้ปัญหาที่สวยงาม แต่จนถึงตอนนี้ดูเหมือนจะเป็นทางออกที่ง่ายอย่างเหลือเชื่อสำหรับทั้งการใช้และการสนับสนุน


ฉันพบสิ่งนี้เพื่อรวบรวมได้อย่างน่าเชื่อถือและเรียบง่าย แอปพลิเคชันที่ใช้เฟรมเวิร์กจำเป็นต้องเชื่อมโยงกับสิ่งใดเป็นพิเศษหรือ CommonCrypto พร้อมใช้งานเสมอหรือไม่
codingFriend1

1
ฉันคิดว่าSecurity.frameworkมีการเชื่อมโยงโดยอัตโนมัติ (มันเป็นเพียงเล็กน้อยหลังจากที่เริ่มโครงการใหม่) หากคุณได้รับข้อผิดพลาดนั่นคือเฟรมเวิร์กสำหรับลิงก์
Rob Napier

ดูเหมือนจะเป็นวิธีการแก้ปัญหาที่ง่ายที่สุดและใช้งานได้ดีกับเครื่องหนึ่ง แต่เมื่อใดก็ตามที่ฉันใช้เฟรมเวิร์กในเฟรมเวิร์กหรือแอปอื่นในเครื่องอื่นฉันจะได้รับข้อผิดพลาด 'โมดูลหายไป'
richever

2

ฉันรู้ว่านี่เป็นคำถามเก่า แต่ฉันคิดหาวิธีอื่นในการใช้ห้องสมุดในโครงการ Swift ซึ่งอาจเป็นประโยชน์สำหรับผู้ที่ไม่ต้องการนำเข้ากรอบงานที่แนะนำในคำตอบเหล่านี้

ในโครงการ Swift สร้างส่วนหัว Bridging 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"

แล้วในคลาส 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ไม่ต้องเป็นสาธารณะ)
กราฟิลส์

แต่ฉันควรเชื่อมโยงกรอบระบบปฏิบัติการใดเพื่อใช้สิ่งนี้ แตกต่างจากคนอื่น ๆ - ฉันต้องทำงานร่วมกับ CommonCrypto ในโครงการ Obj-C และพักคนเดียวบน Xcode 9 กับ MacOS-10.13 SDK
Motti Shneor

@MottiShneor เชื่อมโยงระบบปฏิบัติการใด ๆ ตั้งแต่ 10.9 ขึ้นไป ฉันทำงานในสภาพแวดล้อมเดียวกันและใช้งานได้ดี
Terence

2

ฉันได้เพิ่มเวทมนตร์ 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"

ทำงานเหมือนมีเสน่ห์ :)


คุณสามารถให้โครงการตัวอย่างหรือตัวอย่างเฟรมเวิร์กเดียวกันพร้อมกับไฟล์ spec ของ pod
Gowtham

0

ฉันไม่แน่ใจว่ามีอะไรเปลี่ยนแปลงกับ Xcode 9.2 หรือไม่ แต่ตอนนี้มันง่ายกว่าที่จะทำสิ่งนี้ให้สำเร็จ สิ่งเดียวที่ฉันต้องทำคือสร้างโฟลเดอร์ชื่อ "CommonCrypto" ในไดเรกทอรีโครงการเฟรมเวิร์กของฉันและสร้างไฟล์สองไฟล์ไว้ข้างในไฟล์หนึ่งชื่อ "cc.h" ดังต่อไปนี้:

#include <CommonCrypto/CommonCrypto.h>
#include <CommonCrypto/CommonRandom.h>

และอีกโมดูลหนึ่งเรียกว่าโมดูลโมดูล:

module CommonCrypto {
    export *
    header "cc.h"
}

(ฉันไม่รู้ว่าทำไมคุณไม่สามารถอ้างอิงไฟล์ส่วนหัวจากพื้นที่ SDKROOT โดยตรงในไฟล์ modulemap แต่ฉันไม่สามารถใช้งานได้)

สิ่งที่สามคือการค้นหาการตั้งค่า "นำเข้าเส้นทาง" และตั้งค่าเป็น $ (SRCROOT) ในความเป็นจริงคุณสามารถตั้งค่าเป็นโฟลเดอร์ใดก็ได้ที่คุณต้องการให้โฟลเดอร์ CommonCrypto อยู่ภายใต้หากคุณไม่ต้องการให้อยู่ในระดับราก

หลังจากนี้คุณควรจะสามารถใช้

import CommonCrypto

ในไฟล์ที่รวดเร็วและทุกประเภท / ฟังก์ชั่น / ฯลฯ มีอยู่

แม้ว่าจะมีคำเตือน - หากแอปของคุณใช้ libCommonCrypto (หรือ libcoreCrypto) เป็นเรื่องง่ายสำหรับแฮกเกอร์ที่ไม่ซับซ้อนเกินกว่าจะแนบ debugger ไปยังแอปของคุณ


0

ในกรณีที่คุณมีปัญหาด้านล่าง:

ld: ไม่พบไลบรารีสำหรับ -lapple_crypto clang: ข้อผิดพลาด: คำสั่ง linker ล้มเหลวด้วยรหัสออก 1 (ใช้ -v เพื่อดูการเรียกใช้)

ใน Xcode 10, Swift 4.0 CommonCrypto เป็นส่วนหนึ่งของกรอบงาน

เพิ่ม

 import CommonCrypto

ลบ

  • ไฟล์ CommonCrpto lib จากลิงก์ไบนารีพร้อมกับไลบรารีจาก Build เฟส
  • import CommonCrypto จากส่วนหัว Bridging

สิ่งนี้ได้ผลสำหรับฉัน!


-1

มันเกิดขึ้นกับฉันหลังจากอัปเดต Xcode ฉันลองทุกอย่างที่ทำได้เช่นติดตั้ง cocoapods ใหม่และทำความสะอาดโครงการ แต่มันไม่ได้ผล ตอนนี้มันได้รับการแก้ไขหลังจากรีสตาร์ทระบบ


-13

มันง่ายมาก เพิ่ม

#import <CommonCrypto/CommonCrypto.h>

เป็นไฟล์. h (ไฟล์เชื่อมต่อส่วนหัวของโครงการของคุณ) ตามแบบแผนคุณสามารถเรียกมันว่า YourProjectName-Bridging-Header.h

จากนั้นไปที่โครงการสร้างการตั้งค่าและค้นหา Swift Compiler - การสร้างรหัส ใต้ชื่อนั้นให้เพิ่มชื่อส่วนหัวการเชื่อมต่อของคุณไปยังรายการ "Objetive-C Bridging Header"

คุณทำเสร็จแล้ว ไม่จำเป็นต้องนำเข้ารหัส Swift ของคุณ ส่วนหัว Objective-C สาธารณะใด ๆ ที่ระบุไว้ในไฟล์ส่วนหัวการเชื่อมต่อนี้จะมองเห็นได้โดย Swift


เมธอดของคุณส่งคืนข้อผิดพลาด: การใช้ส่วนเชื่อมต่อ
บริดจ์

5
@ gorgi93 คุณไม่สามารถใช้ส่วนหัวการเชื่อมโยงในเป้าหมายเฟรมเวิร์กได้เนื่องจากข้อผิดพลาดแนะนำ ตัวเลือกเดียวคือการวางไว้ในไฟล์ส่วนหัวของกรอบหลักขออภัย
Charles A.

1
หากคุณมีชื่อของเธรดนี้เป็นสีแดงคุณจะเห็นว่าคนที่แต่งตัวประหลาดต้องการนำเข้าไลบรารี CommonCrypto ไปยังเฟรมเวิร์ก Swift คุณไม่สามารถใช้การเชื่อมต่อส่วนหัวในกรอบงานและคุณไม่สามารถนำเข้ากรอบงาน CommonCrypto ในส่วนหัวของร่ม
miken.mkndev
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.