Azimjon Abdurasulov

05. Adapter: Eski Callback SDK ni Zamonaviy Swift 6 ga Moslash

🏛️ iOS Design Patterns — Mukammal Enterprise & Architecture Qo‘llanma

05. Structural: Adapter Pattern — Eski va Yangi Dunyo Ko'prigi

"Siz yangi uyingizga eng zamonaviy yevro-vilka sotib oldingiz, ammo devordagi rozetka eski sovet standartida. Rozetkani buzib devorni sindirasizmi yoki 1 dollarlik o'tish moslamasi (adapter) qo'yasizmi? Adapter patterni dasturiy ta'minotning aynan o'sha o'tish moslamasidir."


1. Adapter Pattern Nima va U Qaysi Muammoni Hal Qiladi?

Adapter (Wrapper) — bu ikki xil mos kelmaydigan interfeysga ega bo'lgan sinflarni bir-biri bilan hamkorlikda ishlashiga imkon beruvchi tuzilmaviy pattern.

flowchart LR
    Client["Bizning Swift 6 Ilovamiz\n(Kutadi: async/await Protocol)"] --> Adapter["LocationServiceAdapter\n(Moslashtiruvchi Ko'prik)"]
    Adapter --> LegacySDK["Eski 3rd Party SDK\n(Obj-C / Callback Closures / Delegates)"]

    style Client fill:#131720,stroke:#bef264,stroke-width:2px
    style Adapter fill:#181d26,stroke:#7da2ce,stroke-width:2px
    style LegacySDK fill:#251014,stroke:#f87171,stroke-width:1px

Haqiqiy iOS Loyihalardagi Muammo:

  1. Kompaniyangiz eski Objective-C da yozilgan yoki begona kompaniyaning xunuk SDK'sini (masalan, eski Xaritalar yoki To'lov SDK'si) ishlatishga majbur.
  2. Bu SDK eski completion-handler callbacklar yoki murakkab xunuk metodlar bilan ishlaydi.
  3. Agar siz butun ViewModel va Use Case laringiz ichiga o'sha xunuk SDK sinflarini to'g'ridan-to'g'ri chaqirib yozsangiz, ertaga o'sha SDK'ni boshqasiga (masalan, Google Maps'dan Apple MapKit'ga) almashtirishga to'g'ri kelsa — butun loyihaning 50 ta faylini qayta yozishingizga to'g'ri keladi!

2. Class Adapter vs Object Adapter: Nega Swift'da Composition G'alaba Qozonadi?

Nazariyada ikkita turli Adapter mavjud:

  1. Class Adapter: Vorislik (Inheritance) orqali eski sinfdan meros oladi va yangi protokolni tasdiqlaydi. Swift'da ko'p karra vorislik (Multiple Inheritance) taqiqlangani sababli bu usul deyarli ishlatilmaydi.
  2. Object Adapter: Kompozitsiya (Composition) orqali eski SDK'ni o'zining ichida xususiy (private) obyekt sifatida saqlaydi va unga so'rovlarni uzatadi. Bu eng xavfsiz va moslashuvchan yo'ldir.

3. Real-World Swift 6 Kodi: Callback SDK ni async/await ga Moslash

Keling, eski 3rd party GPS SDK'sini zamonaviy Swift 6 talablariga moslashtiramiz.

1. Eski Tashqi SDK (Biz uning kodini o'zgartira olmaymiz):

// Begona kompaniya kutubxonasi (Legacy SDK)
public final class LegacyTrackerSDK {
    public func fetchCoordinates(completion: @escaping (Double, Double, Error?) -> Void) {
        DispatchQueue.global().asyncAfter(deadline: .now() + 1.0) {
            // Sun'iy koordinata qaytarish
            completion(41.311081, 69.240562, nil)
        }
    }
}

2. Bizning Loyihamiz Qabul Qiladigan Zamonaviy Kontrakt:

public struct UserLocation: Sendable {
    public let latitude: Double
    public let longitude: Double
}

public protocol LocationService: Sendable {
    func getCurrentLocation() async throws -> UserLocation
}

3. Object Adapter:

public enum LocationError: Error {
    case locationUnavailable
}

public final class LegacyLocationAdapter: LocationService {
    private let legacySDK: LegacyTrackerSDK
    
    public init(legacySDK: LegacyTrackerSDK = LegacyTrackerSDK()) {
        self.legacySDK = legacySDK
    }
    
    public func getCurrentLocation() async throws -> UserLocation {
        // Swift Concurrency ning CheckedContinuation imkoniyati
        // eski callback'ni zamonaviy async/await ga o'girishda eng yaxshi adapterdir!
        return try await withCheckedThrowingContinuation { continuation in
            legacySDK.fetchCoordinates { lat, lng, error in
                if let error = error {
                    continuation.resume(throwing: error)
                } else {
                    let location = UserLocation(latitude: lat, longitude: lng)
                    continuation.resume(returning: location)
                }
            }
        }
    }
}

4. ViewModel'da Ishlatilishi:

@MainActor
public final class MapViewModel {
    private let locationService: any LocationService
    
    public init(locationService: any LocationService) {
        self.locationService = locationService
    }
    
    public func updatePosition() async {
        do {
            let loc = try await locationService.getCurrentLocation()
            print("Foydalanuvchi manzili: \(loc.latitude), \(loc.longitude)")
        } catch {
            print("Xatolik: \(error)")
        }
    }
}

4. Katta Yutuq: SDK ni 1 Soniyada Almashtirish

Tasavvur qiling, 6 oydan keyin kompaniya rahbariyati: "LegacyTrackerSDK juda qimmat ekan, keling Apple'ning CoreLocation tizimiga o'tamiz" dedi.

Siz ViewModel yoki ekranlarga birorta ham o'zgartirish kiritmaysiz! Siz shunchaki yangi CoreLocationAdapter yozasiz va Dependency Injection orqali uzatasiz:

public final class AppleCoreLocationAdapter: LocationService {
    public func getCurrentLocation() async throws -> UserLocation {
        // CoreLocation async API
        return UserLocation(latitude: 41.31, longitude: 69.24)
    }
}

Bu toza arxitekturaning va Adapter patternining chinakam qudratidir!


5. Interaktiv Savol-Javob (Self-Check Quiz)

<details> <summary><b>1-Savol: Swift'da 'withCheckedContinuation' va 'withCheckedThrowingContinuation' funksiyalari qanday qilib til darajasidagi Adapter hisoblanadi?</b> (Yechimni ko'rish uchun bosing)</summary>

Tahlil va Yechim: Ushbu funksiyalar eski oqim (Completion-handler / Delegate) interfeysini qabul qilib, uni Swift Concurrency (async/await) ga moslashtirib beruvchi standart Apple adapteri vazifasini bajaradi. Ular eski asinxron kodni to'xtatib turadi (await) va natija kelganda davom ettiradi (resume). </details>

<details> <summary><b>2-Savol: Adapter va Facade patternlarining asosiy farqi nimada?</b> (Yechimni ko'rish uchun bosing)</summary>

Tahlil va Yechim:

  • Adapter mavjud interfeysni boshqa bir aniq kutilayotgan interfeysga moslashtirish (Convert/Translate qilish) uchun ishlatiladi.
  • Facade esa interfeysni moslashtirmaydi, balki ko'plab murakkab tizimlarning ustiga yangidan bitta sodda boshqaruv oynasi qurib beradi (Simplification).

</details>


6. Amaliy Topshiriq (Senior Challenge)

Ilovangizda eski NotificationCenter orqali xabar uzatuvchi tizim mavjud:

  • Ushbu eski xabarlashuvni AsyncStream<String> orqali zamonaviy Swift 6 oqimiga aylantirib beruvchi NotificationCenterAdapter sinfini yarating!

Markdown manba

iOS Lessons