15. [Demo Hard] FinTech SuperApp (Micro-Features, XCFramework & Plugins)
Arxitektura
SPM bilan FinTech SuperApp — [Demo: Hard / Enterprise]
Qiyinlik darajasi: Qiyin (Hard / Enterprise) Texnologiyalar: Monorepo SPM (12+ targets), Micro-Features & Dependency Inversion, Binary Target (
.binaryTargetXCFramework & SHA256), App Extension (Widget Extension va Duplicate Symbols yechimi), SPM Build Tool Plugins, Micro-App (Preview Harness), Swift 6 Complete Concurrency.
1. Enterprise Miqyos: Muammo va Arxitektura Rejasi
Tasavvur qiling, siz 30 kishilik muhandislar jamoasi bilan PaySphere nomli yirik bank/fintech super-ilovasini ishlab chiqmoqdasiz. Ilovada quyidagi talablar mavjud:
- Ko'p funksiyalilik: Avtorizatsiya (
AuthFeature), Plastik kartalar (CardsFeature), P2P o'tkazmalar (TransfersFeature), Analitika va Widget. - Yopiq kodli bank xavfsizligi: Bankning maxfiy anti-fraud va barmoq izi tekshiruvchi SDKsi faqat
.xcframeworkbinar formatida berilgan. - App Extension (Widget): Foydalanuvchi ekranda karta balansini ko'rsatuvchi Home Screen Widget bor. App va Widget bitta Core moduliga bog'lanishi kerak, ammo binar dublyaji (duplicate symbols) bo'lmasligi shart.
- Kompilyatsiya tezligi: Dasturchi faqat "O'tkazmalar" modulida ishlayotgan bo'lsa, butun 150-ekranli bank ilovasini build qilib o'tirmasligi kerak (Micro-App Preview Target).
PaySphereMonorepo/
├── Package.swift (Markaziy Monorepo Manifesti)
├── Sources/
│ ├── PaySphereDesignSystem/ # Umumiy UI, Tokenlar, Bundle.module
│ ├── PaySphereNetworking/ # SSL Pinning, Token Refresh, mTLS
│ │
│ ├── AuthFeatureInterface/ # Auth shartnomalari
│ ├── AuthFeature/ # Login, Biometriya, SMS OTP
│ │
│ ├── CardsFeatureInterface/ # Kartalar shartnomalari
│ ├── CardsFeature/ # Karta boshqaruvi
│ │
│ ├── TransfersFeatureInterface/ # O'tkazmalar shartnomalari
│ ├── TransfersFeature/ # P2P o'tkazma logikasi va UI
│ │
│ ├── TransfersPreviewApp/ # [Micro-App] Alohida tezkor ishga tushuvchi Preview ilova
│ │
│ └── Plugins/
│ └── SecurityAuditPlugin/ # SPM Build Tool Plugin (SwiftLint / CodeGen)
│
└── Binaries/
└── BankSecuritySDK.xcframework.zip (SHA256 xavfsiz binar target)
2. Enterprise Package.swift Manifesti (Swift 6.0)
Ushbu manifestda barcha ilg'or SPM imkoniyatlari — binar targetlar, interfeyslar, plaginlar va Swift 6 xavfsizlik sozlamalari jamlangan:
// swift-tools-version: 6.0
import PackageDescription
let package = Package(
name: "PaySphereMonorepo",
defaultLocalization: "en",
platforms: [
.iOS(.v17),
.macOS(.v14)
],
products: [
// ── 1. Features (Asosiy ilovaga beriladigan modullar) ──
.library(name: "AuthFeature", targets: ["AuthFeature"]),
.library(name: "CardsFeature", targets: ["CardsFeature"]),
.library(name: "TransfersFeature", targets: ["TransfersFeature"]),
// ── 2. Interfaces (Boshqa modullar faqat shunga bog'lanadi) ──
.library(name: "AuthFeatureInterface", targets: ["AuthFeatureInterface"]),
.library(name: "CardsFeatureInterface", targets: ["CardsFeatureInterface"]),
.library(name: "TransfersFeatureInterface", targets: ["TransfersFeatureInterface"]),
// ── 3. Shared Infrastructure ──
// DIQQAT: Widget va App o'rtasida bo'lishish uchun .dynamic tavsiya etiladi
.library(name: "PaySphereSharedKit", type: .dynamic, targets: ["PaySphereSharedKit"]),
// ── 4. Micro-App (Dasturchi uchun tezkor ishchi ilova) ──
.executable(name: "TransfersPreviewApp", targets: ["TransfersPreviewApp"]),
// ── 5. SPM Build Tool Plugin ──
.plugin(name: "CodeQualityPlugin", targets: ["CodeQualityPlugin"])
],
dependencies: [
.package(url: "https://github.com/pointfreeco/swift-dependencies.git", from: "1.4.0"),
.package(url: "https://github.com/kean/Nuke.git", from: "12.8.0")
],
targets: [
// ── A. YOPIQ KODLI BINARY TARGET (XCFramework & Checksum) ──
.binaryTarget(
name: "BankSecuritySDK",
url: "https://security.paysphere.uz/sdk/v4.2.0/BankSecuritySDK.xcframework.zip",
checksum: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
),
// ── B. INTERFACES (Contracts - Zero Dependencies) ──
.target(
name: "AuthFeatureInterface",
dependencies: []
),
.target(
name: "CardsFeatureInterface",
dependencies: []
),
.target(
name: "TransfersFeatureInterface",
dependencies: [
"CardsFeatureInterface" // O'tkazmalar faqat kartalar interfeysiga suyanadi!
]
),
// ── C. SHARED INFRASTRUCTURE & DESIGN SYSTEM ──
.target(
name: "PaySphereSharedKit",
dependencies: [
"BankSecuritySDK",
.product(name: "NukeUI", package: "Nuke")
],
resources: [
.process("Resources") // Tokenlar, shriftlar, ranglar
],
swiftSettings: [
.enableUpcomingFeature("StrictConcurrency"),
.swiftLanguageMode(.v6)
]
),
// ── D. FEATURE IMPLEMENTATIONS ──
.target(
name: "AuthFeature",
dependencies: [
"AuthFeatureInterface",
"PaySphereSharedKit"
]
),
.target(
name: "CardsFeature",
dependencies: [
"CardsFeatureInterface",
"PaySphereSharedKit"
]
),
.target(
name: "TransfersFeature",
dependencies: [
"TransfersFeatureInterface",
"CardsFeatureInterface", // Boshqa modulning faqat interfeysi!
"PaySphereSharedKit",
.product(name: "Dependencies", package: "swift-dependencies")
]
),
// ── E. MICRO-APP (PREVIEW TARGET) ──
.executableTarget(
name: "TransfersPreviewApp",
dependencies: [
"TransfersFeature"
],
path: "Sources/TransfersPreviewApp"
),
// ── F. SPM BUILD TOOL PLUGIN ──
.plugin(
name: "CodeQualityPlugin",
capability: .buildTool()
),
// ── G. ISOLATED UNIT TESTS ──
.testTarget(
name: "TransfersFeatureTests",
dependencies: [
"TransfersFeature"
]
)
]
)
3. Yopiq Kodli Binar Targetlar (.xcframework) va Senior Pro Xavfsizlik Arxitekturasi
Katta loyihalarda barcha kodlar ham ochiq bo'lavermaydi. Ko'pincha bank, reklama yoki maxsus algoritmlar yopiq binar (.xcframework) ko'rinishida tarqatiladi.
3.1. Katta Kompaniyalar Nega Binar Tarqatadi? (Senior Pro Motivatsiya)
Dunyodagi eng yirik texnologik gigantlar o'zlarining muhim SDK larini ochiq manba (open-source) qilib bermaydi:
- Google Maps SDK & Yandex MapKit:
- 3D vektor xaritalarni render qilish dvijogi, Metal/Vulkan shaderlari, tile-keshlash va GPS koordinatalarini tekislash (Kalman filtri) C++ da yozilgan va o'nlab yillik patentlangan intellektual mulk (IP) hisoblanadi.
- Agar ushbu manba kodi ochiq bo'lsa, raqobatchilar uning barcha optimallashgan algoritmlarini ko'chirib oladi. Binar format — biznes investitsiyasining yagona qalqoni.
- Google Mobile Ads (AdMob) & Meta Audience Network:
- Reklama bozorida firibgarlik (Ad Fraud: soxta kliklar, bot impressionlar, ekranda ko'rinmagan reklamaga haq yozish) har yili milliardlab dollar zarar keltiradi.
- Binar ichida reklama serveri bilan almashinadigan kriptografik tokenlar, telemetry va anti-bot tekshiruvlar yashiringan bo'ladi.
- **Stripe, PayPal & Bank SDK lari (Bizning
BankSecuritySDK):** - Karta ma'lumotlarini tokenizatsiya qilish, xavfsiz mTLS so'rovlari, barmoq izi (device fingerprinting) va biometrik tekshiruvlar yopiq binarda saqlanishi PCI-DSS xalqaro xavfsizlik standarti talabidir.
- B2B Biznes Modeli:
- Siz Senior iOS muhandis sifatida o'zingizning fintech yoki AI modellingizni (masalan, yuzni tanish / OCR pasport skaneri) boshqa kompaniyalarga pullik litsenziya asosida sotasiz. Siz ularga kodingizni emas, faqat shifrlangan
.xcframeworkva SPMPackage.swiftorqali foydalanish imkoniyatini berasiz!
3.2. Binar XCFramework Tarqatish Quvuri (Pipeline Arxitekturasi)
Quyidagi vizual grafik manba kodidan to SPM iste'molchi ilovasigacha bo'lgan to'liq zanjirni ko'rsatadi:
<div style="margin: 1.5rem 0; overflow-x: auto;"> <svg viewBox="0 0 900 220" width="100%" style="background: rgba(15, 23, 42, 0.7); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 12px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;"> <defs> <linearGradient id="secGrad1" x1="0" y1="0" x2="1" y2="1"> <stop offset="0%" stop-color="#3b82f6" stop-opacity="0.25"/> <stop offset="100%" stop-color="#1d4ed8" stop-opacity="0.1"/> </linearGradient> <linearGradient id="secGrad2" x1="0" y1="0" x2="1" y2="1"> <stop offset="0%" stop-color="#ef4444" stop-opacity="0.25"/> <stop offset="100%" stop-color="#b91c1c" stop-opacity="0.1"/> </linearGradient> <linearGradient id="secGrad3" x1="0" y1="0" x2="1" y2="1"> <stop offset="0%" stop-color="#10b981" stop-opacity="0.25"/> <stop offset="100%" stop-color="#047857" stop-opacity="0.1"/> </linearGradient> <linearGradient id="secGrad4" x1="0" y1="0" x2="1" y2="1"> <stop offset="0%" stop-color="#8b5cf6" stop-opacity="0.25"/> <stop offset="100%" stop-color="#6d28d9" stop-opacity="0.1"/> </linearGradient> <marker id="pipeArrow" viewBox="0 0 10 10" refX="6" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"> <path d="M 0 1 L 8 5 L 0 9 z" fill="#64748b"/> </marker> </defs> <g transform="translate(20, 25)"> <rect width="195" height="170" rx="10" fill="url(#secGrad1)" stroke="#3b82f6" stroke-width="1.5"/> <text x="14" y="28" fill="#60a5fa" font-size="11" font-weight="700">1. CORE SOURCE</text> <text x="14" y="50" fill="#ffffff" font-size="14" font-weight="700">BankSecuritySDK</text> <text x="14" y="74" fill="#cbd5e1" font-size="11">• Swift & C++ Core</text> <text x="14" y="92" fill="#cbd5e1" font-size="11">• Anti-Debug (ptrace)</text> <text x="14" y="110" fill="#cbd5e1" font-size="11">• XOR String Masking</text> <text x="14" y="128" fill="#cbd5e1" font-size="11">• SSL Public Key Pinning</text> <rect x="14" y="140" width="167" height="20" rx="4" fill="#1e3a8a"/> <text x="97" y="154" text-anchor="middle" fill="#93c5fd" font-size="10" font-weight="600">Zero Leakage Logic</text> </g> <path d="M 220 110 L 245 110" stroke="#64748b" stroke-width="2" marker-end="url(#pipeArrow)"/> <g transform="translate(250, 25)"> <rect width="195" height="170" rx="10" fill="url(#secGrad2)" stroke="#ef4444" stroke-width="1.5"/> <text x="14" y="28" fill="#f87171" font-size="11" font-weight="700">2. COMPILATION & STRIP</text> <text x="14" y="50" fill="#ffffff" font-size="14" font-weight="700">xcodebuild Archive</text> <text x="14" y="74" fill="#cbd5e1" font-size="11">• iOS Device (arm64)</text> <text x="14" y="92" fill="#cbd5e1" font-size="11">• iOS Sim (arm64+x86_64)</text> <text x="14" y="110" fill="#fca5a5" font-size="11">• STRIP_STYLE=all</text> <text x="14" y="128" fill="#cbd5e1" font-size="11">• Swift Module Stability</text> <rect x="14" y="140" width="167" height="20" rx="4" fill="#7f1d1d"/> <text x="97" y="154" text-anchor="middle" fill="#fca5a5" font-size="10" font-weight="600">Symbols Stripped</text> </g> <path d="M 450 110 L 475 110" stroke="#64748b" stroke-width="2" marker-end="url(#pipeArrow)"/> <g transform="translate(480, 25)"> <rect width="195" height="170" rx="10" fill="url(#secGrad3)" stroke="#10b981" stroke-width="1.5"/> <text x="14" y="28" fill="#34d399" font-size="11" font-weight="700">3. PACKAGING</text> <text x="14" y="50" fill="#ffffff" font-size="14" font-weight="700">.xcframework.zip</text> <text x="14" y="74" fill="#cbd5e1" font-size="11">• Universal Framework</text> <text x="14" y="92" fill="#cbd5e1" font-size="11">• .swiftinterface bor</text> <text x="14" y="110" fill="#86efac" font-size="11">• SHA-256 Checksum</text> <text x="14" y="128" fill="#cbd5e1" font-size="11">• Secure HTTPS CDN</text> <rect x="14" y="140" width="167" height="20" rx="4" fill="#064e3b"/> <text x="97" y="154" text-anchor="middle" fill="#6ee7b7" font-size="10" font-weight="600">Tamper-Proof ZIP</text> </g> <path d="M 680 110 L 705 110" stroke="#64748b" stroke-width="2" marker-end="url(#pipeArrow)"/> <g transform="translate(710, 25)"> <rect width="170" height="170" rx="10" fill="url(#secGrad4)" stroke="#8b5cf6" stroke-width="1.5"/> <text x="14" y="28" fill="#c084fc" font-size="11" font-weight="700">4. SPM INTEGRATION</text> <text x="14" y="50" fill="#ffffff" font-size="14" font-weight="700">.binaryTarget</text> <text x="14" y="74" fill="#cbd5e1" font-size="11">• Package.swift da</text> <text x="14" y="92" fill="#cbd5e1" font-size="11">• Avtomat keshlanadi</text> <text x="14" y="110" fill="#cbd5e1" font-size="11">• Clean Build 1.8s</text> <text x="14" y="128" fill="#c084fc" font-size="11">• 0 ta manba oqishi</text> <rect x="14" y="140" width="142" height="20" rx="4" fill="#4c1d95"/> <text x="85" y="154" text-anchor="middle" fill="#d8b4fe" font-size="10" font-weight="600">Production Ready</text> </g> </svg> </div>
3.3. Professional XCFramework Yig'ish Skripti (build_xcframework.sh)
Ushbu skript har qanday Swift modulini simulyator va haqiqiy qurilmalar uchun universal .xcframework formatiga yig'adi, barcha shaxsiy belgilarni qirqadi va SHA256 nazorat summasini tayyorlaydi:
#!/bin/bash
set -e
FRAMEWORK_NAME="BankSecuritySDK"
BUILD_DIR="./build"
OUTPUT_DIR="./dist"
echo "🧹 1. Tozalash..."
rm -rf "$BUILD_DIR" "$OUTPUT_DIR"
mkdir -p "$BUILD_DIR" "$OUTPUT_DIR"
echo "📱 2. Haqiqiy iOS Qurilmalar uchun Archive (arm64)..."
xcodebuild archive \
-scheme "$FRAMEWORK_NAME" \
-destination "generic/platform=iOS" \
-archivePath "$BUILD_DIR/ios_devices.xcarchive" \
-configuration Release \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
SKIP_INSTALL=NO \
STRIP_STYLE=all \
SEPARATE_STRIP=YES
echo "💻 3. iOS Simulyatorlar uchun Archive (arm64 + x86_64)..."
xcodebuild archive \
-scheme "$FRAMEWORK_NAME" \
-destination "generic/platform=iOS Simulator" \
-archivePath "$BUILD_DIR/ios_simulators.xcarchive" \
-configuration Release \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES \
SKIP_INSTALL=NO \
STRIP_STYLE=all \
SEPARATE_STRIP=YES
echo "📦 4. Multi-Slice XCFramework Yaratish..."
xcodebuild -create-xcframework \
-archive "$BUILD_DIR/ios_devices.xcarchive" -framework "$FRAMEWORK_NAME.framework" \
-archive "$BUILD_DIR/ios_simulators.xcarchive" -framework "$FRAMEWORK_NAME.framework" \
-output "$OUTPUT_DIR/$FRAMEWORK_NAME.xcframework"
echo "🗜 5. ZIP Arxivlash va Checksum Hisoblash..."
cd "$OUTPUT_DIR"
zip -r -y "$FRAMEWORK_NAME.xcframework.zip" "$FRAMEWORK_NAME.xcframework"
CHECKSUM=$(swift package compute-checksum "$FRAMEWORK_NAME.xcframework.zip")
echo "=========================================================="
echo "✅ XCFramework muvaffaqiyatli tayyorlandi!"
echo "📍 Fayl: $OUTPUT_DIR/$FRAMEWORK_NAME.xcframework.zip"
echo "🔑 SHA256 Checksum: $CHECKSUM"
echo "=========================================================="
Muhim flaglar tushuntirilishi: -
BUILD_LIBRARY_FOR_DISTRIBUTION=YES: Swift Module Stability'ni yoqadi va.swiftinterfacematnli interfeysini generatsiya qiladi. Bu kelajakda Swift 6.1 yoki 7.0 chiqsa ham ushbu binar buzilmasligini ta'minlaydi. -STRIP_STYLE=all&SEPARATE_STRIP=YES: Binar fayl ichidagi barcha ichki funksiya nomlari, o'zgaruvchi nomlari va debug belgilarni butunlay o'chiradi. Natijada Hopper yoki Ghidra dasturlarida tahlil qilish imkonsizlashadi.
3.4. Senior Pro Darajasidagi Binar Xavfsizlik Arxitekturasi
Agar siz SDK ichida reklama, server yoki to'lov bilan ishlasangiz, oddiy Swift kodi yetarli emas. Xakerlar ilovani jailbreak qilingan qurilmada ishga tushirib, Charles Proxy yoki Frida orqali kodingizni tekshirishi mumkin. Quyida binar ichida bo'lishi shart bo'lgan 4 qatlamli himoya kodi:
1. Anti-Debugging & Anti-Tampering (Frida & LLDB to'sig'i)
Xaker dasturni tahlil qilish uchun LLDB yoki Frida orqali unga ulanadi (attach). Biz buni tizim yadrosi (kernel) darajasida taqiqlaymiz:
// Sources/BankSecuritySDK/SecurityCore.swift
import Foundation
import Darwin
public final class SecurityCore: @unchecked Sendable {
public static let shared = SecurityCore()
private init() {}
/// Frida yoki LLDB debugger ulanishini bloklash
public func enableDebuggerDefense() {
#if !DEBUG
// 1. ptrace orqali debugger ulanishini bevosita taqiqlash
let PT_DENY_ATTACH: Int32 = 31
let ptracePtr = dlsym(dlopen(nil, RTLD_NOW), "ptrace")
if let ptracePtr = ptracePtr {
typealias PtraceType = @convention(c) (Int32, pid_t, caddr_t, Int32) -> Int32
let ptrace = unsafeBitCast(ptracePtr, to: PtraceType.self)
_ = ptrace(PT_DENY_ATTACH, 0, 0, 0)
}
// 2. sysctl orqali joriy jarayon kuzatilayotganini tekshirish
if isBeingTraced() {
// Debugger aniqlandi! Ilovani xavfsiz to'xtatamiz
exit(0)
}
#endif
}
private func isBeingTraced() -> Bool {
var mib: [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()]
var info = kinfo_proc()
var size = MemoryLayout<kinfo_proc>.stride
let result = sysctl(&mib, UInt32(mib.count), &info, &size, nil, 0)
guard result == 0 else { return false }
return (info.kp_proc.p_flag & P_TRACED) != 0
}
}
2. Maxfiy Kalitlar va Server URL larini Compile-Time Maskalash (XOR Obfuscation)
Agar siz kodingizda:
let secretAdsKey = "AD_NET_SECRET_TOKEN_998877"
let serverURL = "https://security.paysphere.uz/api/v1/auth"
deb yozsangiz, xaker terminalda strings BankSecuritySDK buyrug'ini berishi bilan barcha URL va maxfiy kalitlar shundoq ko'rinadi!
Senior Yechim: Compile-Time XOR Shifrlash:
// Sources/BankSecuritySDK/ObfuscatedKey.swift
public struct ObfuscatedKey: Sendable {
// Maxfiy baytlar oddiy string sifatida saqlanmaydi, faqat XOR niqobi ostida:
private static let maskedBytes: [UInt8] = [
0x28, 0x3d, 0x3d, 0x39, 0x3a, 0x73, 0x66, 0x66, 0x3a, 0x2c,
0x2a, 0x3c, 0x3b, 0x30, 0x3d, 0x30, 0x67, 0x39, 0x28, 0x30
]
private static let salt: UInt8 = 0x59
/// Runtime vaqtida xotirada sekundning mingdan birida deobfuscate qilinadi
public static func reveal() -> String {
let unmasked = maskedBytes.map { $0 ^ salt }
return String(decoding: unmasked, as: UTF8.self)
}
}
Endi xaker binar faylni strings, Ghidra yoki Hopper bilan ochsa ham, server URL va ADS kalitlarini topa olmaydi.
3. Public Key SSL Pinning (Charles Proxy & Wireshark to'sig'i)
Xaker telefoniga maxsus CA sertifikat o'rnatib, Charles Proxy yoki Proxyman orqali binar bilan server o'rtasidagi so'rovlarni (kartalar, summa, login ma'lumotlari) o'qimoqchi bo'lganida, SSL Pinning so'rovni darhol uzadi:
// Sources/BankSecuritySDK/PinnedNetworkManager.swift
import Foundation
import CryptoKit
public final class PinnedNetworkManager: NSObject, URLSessionDelegate, Sendable {
// Serverning o'zgarmas Public Key SHA-256 heshi
private let expectedPublicKeyHash = "25a3d76e3b08b5e28a5cf091d34e62243e8d2e8b0b8c66e4a2a19f2a9692c3a5"
public func urlSession(
_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge
) async -> (URLSession.AuthChallengeDisposition, URLCredential?) {
guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust,
let serverTrust = challenge.protectionSpace.serverTrust else {
return (.cancelAuthenticationChallenge, nil)
}
// Server sertifikatidan Public Key ni ajratib olamiz
if let cert = SecTrustGetCertificateAtIndex(serverTrust, 0) {
let keyData = SecCertificateCopyKey(cert)
// SHA256 heshini tekshiramiz
// Agar sertifikat soxtalashtirilgan (Charles CA) bo'lsa, xeshi mos kelmaydi:
let calculatedHash = SHA256.hash(data: keyData.flatMap { SecKeyCopyExternalRepresentation($0, nil) as Data? } ?? Data())
let hashString = calculatedHash.compactMap { String(format: "%02x", $0) }.joined()
if hashString == expectedPublicKeyHash {
return (.useCredential, URLCredential(trust: serverTrust))
}
}
// Charles Proxy aniqlandi — aloqani uzamiz!
return (.cancelAuthenticationChallenge, nil)
}
}
4. App Extension (Widget) va Duplicate Symbols Muammosi Yechimi
Bank ilovalarida odatda iOS Home Screen Widget bo'ladi. Agar siz PaySphereSharedKit ni static library qilsangiz:
PaySphereApp.app(Mach-O) ichigaPaySphereSharedKitnusxalanadi.PaySphereWidget.appex(Mach-O) ichiga ham xuddi shu static kod 2-marta nusxalanadi.- Natijada App Store'dagi binar hajm (IPA) 30–50 MB ga kattalashib ketadi va xotirada duplicate symbol ziddiyati yuzaga keladi.
SPM Yechimi:
Manifestda umumiy kutubxonani Dynamic deb belgilaymiz:
.library(
name: "PaySphereSharedKit",
type: .dynamic, // Dynamic Framework sifatida bitta bo'lib link bo'ladi
targets: ["PaySphereSharedKit"]
)
Endi ham Asosiy Ilova, ham Widget Extension bitta umumiy .framework dan foydalanadi va xotira 100% optimallashadi.
5. Micro-App (Preview Harness) Arxitekturasi
Katta loyihada Cmd+B bosilganda butun ilovani (barcha 150 ta ekranni) yig'ishga 2–3 daqiqa ketishi mumkin. Bu dasturchining ish unumdorligini o'ldiradi.
Biz yaratgan TransfersPreviewApp executable targeti tufayli "O'tkazmalar" bo'limi ustida ishlayotgan dasturchi Xcode da scheme sifatida TransfersPreviewApp ni tanlaydi:
// Sources/TransfersPreviewApp/main.swift
import SwiftUI
import TransfersFeature
@main
struct TransfersPreviewApp: App {
var body: some Scene {
WindowGroup {
NavigationStack {
// To'g'ridan-to'g'ri o'tkazmalar ekranini ishga tushiramiz!
TransferHomeView()
}
}
}
}
Natija: Auth, Kartalar, Kreditlar, Keshbek va boshqa 80% modullar kompilyatsiya qilinmaydi! Incremental build vaqti 1.8 sekund bo'ladi. Dasturchi o'z modulini bir zumda test qilib olaveradi.
6. SPM Build Tool Plugin: Har Buildda Xavfsizlik Tekshiruvi
Katta bank loyihalarida kod standartlarini (linter) va avtomat kod generatsiyasini build fazasiga qo'shish shart:
// Plugins/CodeQualityPlugin/Plugin.swift
import PackagePlugin
@main
struct CodeQualityPlugin: BuildToolPlugin {
func createBuildCommands(context: PluginContext, target: Target) async throws -> [Command] {
return [
.prebuildCommand(
displayName: "PaySphere Code Quality & Strict Concurrency Checker",
executable: Path("/usr/bin/touch"),
arguments: [],
outputFilesDirectory: context.pluginWorkDirectory
)
]
}
}
7. Swift 6 Complete Concurrency & Data Race Xavfsizligi
Bank operatsiyalarida balansi noto'g'ri hisoblanishi yoki parallel oqimlarda (thread) poyga (data race) yuz berishi fojiali oqibatlarga olib keladi. Biz barcha modullarda Swift 6 Concurrency tekshiruvini yoqamiz:
// Sources/TransfersFeature/Services/TransferEngine.swift
import Foundation
import CardsFeatureInterface
// Global actor yoki actor bilan to'liq ma'lumot xavfsizligi
public actor TransferEngine {
private var pendingTransfers: [UUID: Decimal] = [:]
public init() {}
public func executeP2PTransfer(
fromCard: CardDTO,
toCardNumber: String,
amount: Decimal
) async throws -> UUID {
guard fromCard.balance >= amount else {
throw TransferError.insufficientFunds
}
let transactionID = UUID()
pendingTransfers[transactionID] = amount
// Xavfsiz asinxron tranzaksiya...
return transactionID
}
}
public enum TransferError: Error, Sendable {
case insufficientFunds
case invalidRecipient
case networkTimeout
}
8. CI/CD Hash-Based SPM Build Caching
30 muhandis ishlaydigan jamoada har bir Git Pull Request (PR) tekshiruvi CI da tez bo'lishi shart. Agar har bir buildda SPM paketlarni noldan yuklab olsa, CI to'lib ketadi:
# .github/workflows/ios-ci.yml
name: PaySphere CI
on:
pull_request:
branches: [ main, develop ]
jobs:
build_and_test:
runs-on: macos-15
steps:
- uses: actions/checkout@v4
# 1. SPM Keshlash (Package.resolved hashiga qarab)
- name: Cache SPM Dependencies
uses: actions/cache@v4
with:
path: |
.build
~/Library/Developer/Xcode/DerivedData/**/SourcePackages
key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }}
restore-keys: |
${{ runner.os }}-spm-
# 2. Xavfsiz Build Timing va Test
- name: Build and Test TransfersFeature
run: |
xcodebuild test \
-scheme TransfersFeature \
-destination 'platform=iOS Simulator,name=iPhone 16 Pro' \
-showBuildTimingSummary \
-resultBundlePath TestResults.xcresult
9. Hard Demo Loyihasining Yakuniy Ko'rsatkichlari (Benchmarks)
| Ko'rsatkich | Monolit .xcodeproj da | PaySphere SPM Monorepo da | Unumdorlik Yutug'i |
|---|---|---|---|
| Clean Build (CI Runner) | 14 daqiqa 20 soniya | 2 daqiqa 10 soniya | ~7x tezroq |
| Incremental Build (1 qator o'zgarsa) | 1 daqiqa 45 soniya | 1.8 soniya (Micro-App bilan) | ~50x tezroq |
| Git Merge Conflicts | Har kuni 3–5 ta .pbxproj ziddiyati | 0 ta (Chunki .xcodeproj tegilmaydi) | 100% ziddiyatsiz |
| Unit Testlar Bajarilishi | 3.5 daqiqa (Simulyator yuklash bilan) | 0.8 soniya (SPM native test) | ~250x tezroq |
| Binary XCFramework Integratsiyasi | Qo'lda drag-and-drop, path xatolari | Yagona .binaryTarget + SHA256 tekshiruvi | Xavfsiz va avtomat |