XCFramework — یک قالب باینری اپل است که کتابخانهها را برای iOS، macOS، tvOS و watchOS در یک بسته ترکیب میکند. برای جایگزینی .framework و رفع مشکلات باینری چاق در هنگام ساخت برای معماریهای مختلف شبیهساز و دستگاه طراحی شده است. بر اساس اعلام اپل WWDC 2019، XCFramework به قالب اجباری برای تحویل SDKهای پشتیبانیکننده از چندین پلتفرم تبدیل شده و به طور کامل رویکرد قدیمی با باینریهای جهانی را جایگزین کرده است.
نکات اصلی
XCFramework — قالبی برای بستهبندی کتابخانههای باینری و فریمورکها است که توسط اپل در WWDC 2019 معرفی شد. هدف اصلی ایجاد یک باندل واحد است که شامل نسخههای کامپایلشده کتابخانه برای تمام پلتفرمها و معماریهای هدف است.
قبل از ظهور XCFramework، توسعهدهندگان از .framework با باینری چاق استفاده میکردند که چندین معماری را از طریق ابزار lipo ترکیب میکرد. این رویکرد مشکلاتی ایجاد میکرد: هنگام ساخت پروژه برای شبیهساز، باینری چاق هم معماری شبیهساز و هم دستگاه را شامل میشد که منجر به خطا هنگام ارسال بیلد به App Store میشد. توسعهدهندگان مجبور بودند فازهای Run Script برای حذف معماریهای غیرضروری بنویسند.
بر اساس Apple Developer Documentation (2024)، XCFramework از تمام پلتفرمهای اکوسیستم اپل پشتیبانی میکند: iOS، iPadOS، macOS، tvOS، watchOS، visionOS و برنامههای کاتالیست. هر پلتفرم یک برش جداگانه در داخل بسته دریافت میکند که تعارضات معماری را از بین میبرد و توزیع SDK را ساده میکند.
XCFramework در سه سناریوی اصلی استفاده میشود: تحویل SDKهای بسته به توسعهدهندگان شخص ثالث، توزیع ماژولهای بومی برای Flutter و React Native، و انتشار کتابخانههایی که نیاز به کامپایل اولیه دارند. این قالب برای تمام SDKهای جدید منتشرشده در اکوسیستم اپل اجباری است.
توسعهدهندگان XCFramework را انتخاب میکنند وقتی کد منبع قابل افشا نیست، وقتی کتابخانه از الگوریتمهای اختصاصی استفاده میکند یا وقتی حفاظت از مجوز مورد نیاز است. برخلاف Swift Package Manager که با کد منبع کار میکند، XCFramework فایلهای باینری از پیش کامپایلشده را تحویل میدهد.
مشکل باینری چاق این بود که باینری جهانی شامل چندین معماری در یک فایل Mach-O بود. هنگام ساخت برنامه برای شبیهساز، Xcode معماری arm64 دستگاه و x86_64 شبیهساز را در باینری قرار میداد — App Store فقط معماری دستگاه را میپذیرفت.
راهحل سنتی شامل اضافه کردن فاز Run Script با فراخوانی lipo برای حذف معماریهای شبیهساز از بیلد نهایی بود. این رویکرد شکننده بود و با بهروزرسانیهای Xcode یا افزودن معماریهای جدید (مثلاً arm64 برای شبیهساز روی Apple Silicon) خراب میشد.
بر اساس Swift.org (2023)، تیم Swift Package Manager ابتدا هنگام تلاش برای پشتیبانی از وابستگیهای باینری با این مشکل مواجه شد. XCFramework آن را در سطح قالب حل کرد: هر برش یک پوشه جداگانه با Info.plist است که پلتفرم و معماری هدف را توصیف میکند. Xcode به طور خودکار برش مناسب را هنگام ساخت انتخاب میکند و نیازی به پردازش بعدی ندارد.
هر برش در XCFramework فقط یک ترکیب از پلتفرم و معماری را شامل میشود. مثلاً ios-arm64 فقط برای دستگاههای iOS باینری دارد و ios-x86_64-simulator فقط برای شبیهساز Intel Mac. Xcode به طور خودکار برش صحیح را انتخاب میکند و نیاز به اسکریپتهای حذف معماری را از بین میبرد و خطر خطاهای ساخت را کاهش میدهد.
برش ios-arm64-x86_64-simulator برای پشتیبانی از Apple Silicon Mac ایجاد شد. قبلاً برای شبیهساز یک باینری جداگانه برای arm64 (Apple Silicon) و x86_64 (Intel) نیاز بود. XCFramework به باینری چاق در داخل یک برش برای شبیهساز اجازه میدهد — این تنها استثنایی است که باینری چاق توجیهپذیر است.
بسته XCFramework دایرکتوری با پسوند .xcframework است که شامل Info.plist در سطح بالایی و پوشههایی با برشهای باینری است. هر برش شامل کتابخانه .framework یا .a برای یک پلتفرم خاص است.
MyLibrary.xcframework/
Info.plist
ios-arm64/
MyLibrary.framework/
Info.plist
MyLibrary
ios-x86_64-simulator/
MyLibrary.framework/
Info.plist
MyLibrary
macos-arm64-x86_64/
MyLibrary.framework/
Info.plist
MyLibrary
Info.plist بسته شامل کلید AvailableLibraries است که شناسههای LibraryIdentifier، LibraryPath و SupportedPlatform را برای هر برش فهرست میکند. Xcode این فایل را هنگام افزودن XCFramework به پروژه میخواند و به طور خودکار مسیرهای جستجو و فاز Embed Frameworks را پیکربندی میکند.
هر برش یک .framework کامل یا کتابخانه ایستا با Info.plist خاص خود است. این به XCFramework اجازه میدهد از انواع ترکیبی پشتیبانی کند: کتابخانههای ایستا برای برخی پلتفرمها و فریمورکهای پویا برای برخی دیگر، اگرچه در عمل معمولاً از یک نوع برای همه برشها استفاده میشود.
ایجاد XCFramework از طریق xcodebuild -create-xcframework انجام میشود. این دستور کتابخانههای .framework یا .a از پیش ساختهشده برای هر پلتفرم را دریافت کرده و آنها را در یک بسته واحد ترکیب میکند.
فرآیند شامل دو مرحله است: ابتدا باینریها برای هر پلتفرم هدف ساخته میشوند، سپس در XCFramework بستهبندی میشوند. برای ساخت از پرچمهای استاندارد destination Xcode استفاده میشود.
# مرحله 1: فریمورکها را برای هر پلتفرم بسازید
xcodebuild archive -scheme MyLibrary -destination "generic/platform=iOS Simulator"
xcodebuild archive -scheme MyLibrary -destination "generic/platform=iOS"
xcodebuild archive -scheme MyLibrary -destination "generic/platform=macOS"
# مرحله 2: XCFramework ایجاد کنید
xcodebuild -create-xcframework -framework ./iOS/MyLibrary.framework -framework ./iOSSim/MyLibrary.framework -framework ./macOS/MyLibrary.framework -output ./MyLibrary.xcframework
پرچم -create-xcframework در Xcode 11 ظاهر شد. دستور به طور خودکار ساختار دایرکتوری صحیح را ایجاد میکند و Info.plist را با توضیح تمام پلتفرمها تولید میکند. اگر یکی از .framework آسیب دیده یا با معماری اشتباه ساخته شده باشد، xcodebuild در مرحله اعتبارسنجی خطا میدهد.
برای CI/CD از اسکریپت شل استفاده میشود که ساخت زیر همه پلتفرمها و ایجاد XCFramework را خودکار میکند. رویکرد محبوب یک پوسته به شکل Makefile یا لین Fastlane با پارامترسازی scheme و output path است.
# build_xcframework.sh — اسکریپت خودکارسازی
set -e
SCHEME="MyLibrary"
OUTPUT="./build"
xcodebuild archive -scheme "$SCHEME" -sdk iphonesimulator -archivePath "$OUTPUT/sim.xcarchive"
xcodebuild archive -scheme "$SCHEME" -sdk iphoneos -archivePath "$OUTPUT/dev.xcarchive"
xcodebuild -create-xcframework -framework "$OUTPUT/dev.xcarchive/Products/Library/Frameworks/MyLibrary.framework" -framework "$OUTPUT/sim.xcarchive/Products/Library/Frameworks/MyLibrary.framework" -output "$OUTPUT/MyLibrary.xcframework"
چنین اسکریپتی در پایپلاین CI (GitHub Actions، Bitrise، Jenkins) پس از اجرای تستها اجرا میشود. XCFramework حاصل بایگانی شده و به عنوان مصنوع انتشار بارگذاری میشود یا از طریق مدیر وابستگی مانند CocoaPods با استفاده از pod spec منتشر میشود.
اتصال XCFramework در پروژه Xcode نیازی به پیکربندی دستی مسیرهای جستجو ندارد. کافیست .xcframework را به بخش Frameworks, Libraries, and Embedded Content در تنظیمات General target بکشید.
برخلاف .framework، XCFramework نیازی به افزودن فاز Run Script برای حذف معماریهای شبیهساز ندارد. Xcode به طور خودکار برشهای موجود را تعیین کرده و فقط موارد مورد نیاز برای طرح ساخت فعلی را شامل میشود. برای دستگاه فیزیکی از برش ios-arm64 استفاده میشود، برای شبیهساز — ios-arm64-x86_64-simulator یا ios-x86_64-simulator.
import MyLibrary
func processData() {
// XCFramework برش صحیح را در زمان ساخت حل میکند
let processor = DataProcessor()
let result = processor.analyze(input: "sample")
print(result)
}
برای CocoaPods یکپارچهسازی از طریق podspec با مشخص کردن vendored_frameworks و فهرست پلتفرمهای پشتیبانیشده انجام میشود. مدیر وابستگی به طور خودکار تعیین میکند که کدام برشها برای پروژه مورد نیاز است. بسیاری از SDKهای تجاری — Firebase، Adjust، AppsFlyer — برای سادهسازی نصب به XCFramework مهاجرت کردهاند.
Swift Package Manager و XCFramework رقابت نمیکنند بلکه مکمل یکدیگر هستند. SPM با کد منبع کار میکند و وابستگیها را در هر ساخت پروژه کامپایل میکند. XCFramework باینریهای آماده ارائه میدهد و نیازی به کامپایل در سمت مصرفکننده ندارد.
با انتشار Swift Package Manager 5.3، اپل پشتیبانی از وابستگیهای باینری را اضافه کرد — اکنون SPM میتواند XCFramework را به عنوان یک وابستگی راه دور بارگیری کند. Package.swift URL را به مصنوع باینری و چکسام آن برای تأیید مشخص میکند.
بر اساس Swift Package Manager documentation (2024)، وابستگیهای باینری برای SDKهایی که کد منبع را افشا نمیکنند یا برای کتابخانههایی که ساخت آنها زمان نامتناسبی میبرد توصیه میشود. برای پروژههای متنباز، تحویل با کد منبع از طریق SPM ترجیح داده میشود.
| معیار | XCFramework | Swift Package Manager |
|---|---|---|
| قالب | باینری (.xcframework) | کد منبع |
| حفاظت از کد | کامل | خیر |
| زمان ساخت | حداقل (کپی) | بستگی به حجم کد دارد |
| انعطافپذیری پلتفرم | تمام پلتفرمهای اپل | بستگی به Package.swift دارد |
| یکپارچهسازی | کشیدن-رها کردن یا SPM | Package.swift |
سوالات متداول
.framework — قالب قدیمی شامل باینری چاق با معماریهای دستگاه و شبیهساز. XCFramework هر برش را جداگانه ذخیره میکند و تعارضات معماری را هنگام ساخت از بین میبرد. اپل XCFramework را برای همه پروژههای جدید و مهاجرت پروژههای موجود توصیه میکند.
CocoaPods از XCFramework از نسخه 1.9 پشتیبانی میکند. در podspec کافیست spec.vendored_frameworks و spec.static_framework را مشخص کنید. مدیر به طور خودکار وابستگیها را با در نظر گرفتن برشهای موجود برای پلتفرم پروژه حل میکند.
اپل پشتیبانی از .framework را حذف نمیکند، اما برای SDKهای جدید فقط XCFramework را توصیه میکند. هنگام ارسال برنامه به App Store با باینری چاق در قالب قدیمی، خطاهای Invalid Bundle به دلیل معماریهای شبیهساز ممکن است رخ دهد که XCFramework را به یک ضرورت عملی تبدیل میکند.
از Swift 5.3، وابستگیهای باینری در SPM از XCFramework استفاده میکنند. Package.swift آدرس url و چکسام بسته باینری را مشخص میکند. SPM بارگیری میکند، یکپارچگی را تأیید میکند و XCFramework را به عنوان وابستگی سیستمی بدون کامپایل کد منبع متصل میکند.
visionOS در XCFramework از Xcode 15 پشتیبانی میشود. در WWDC 2023 اپل تأیید کرد که قالب برای Apple Vision Pro گسترش یافته است. برش visionOS دارای SupportedPlatform = xros است و شامل معماری arm64 میباشد.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.