Published on

WebSocket va Combine asoslari

Authors

HTTP β€” so'rov yuborib javob kutish. Lekin chat, jonli narxlar, o'yin β€” real-time kerak. WebSocket β€” doimiy ochiq kanal. Combine β€” reaktiv ma'lumot oqimi.

WebSocket asoslari

// ═══════════════════════════════════════
//  WEBSOCKET β€” real-time ulanish
// ═══════════════════════════════════════
class WebSocketMenejer: ObservableObject {
    @Published var xabarlar: [String] = []
    @Published var ulangan = false
    private var webSocketTask: URLSessionWebSocketTask?

    func ulanish() {
        let url = URL(string: "wss://echo.websocket.org")!
        webSocketTask = URLSession.shared.webSocketTask(with: url)
        webSocketTask?.resume()
        ulangan = true

        // Xabar qabul qilishni boshlash
        qabulQilish()
    }

    func xabarYuborish(_ matn: String) {
        let xabar = URLSessionWebSocketTask.Message.string(matn)
        webSocketTask?.send(xabar) { xato in
            if let xato {
                print("Yuborish xatosi: \(xato)")
            }
        }
    }

    private func qabulQilish() {
        webSocketTask?.receive { [weak self] natija in
            switch natija {
            case .success(let xabar):
                switch xabar {
                case .string(let matn):
                    DispatchQueue.main.async {
                        self?.xabarlar.append(matn)
                    }
                case .data(let data):
                    print("Data: \(data.count) bayt")
                @unknown default:
                    break
                }
                // Keyingi xabarni kutish
                self?.qabulQilish()

            case .failure(let xato):
                print("Qabul xatosi: \(xato)")
            }
        }
    }

    func uzish() {
        webSocketTask?.cancel(with: .goingAway, reason: nil)
        ulangan = false
    }
}

Combine asoslari

import Combine

// ═══════════════════════════════════════
//  PUBLISHER VA SUBSCRIBER
// ═══════════════════════════════════════
class HisoblashMisol {
    var cancellables = Set<AnyCancellable>()

    func boshlash() {
        // Publisher β€” har 1 soniyada raqam chiqaradi
        let publisher = Timer.publish(every: 1.0, on: .main, in: .common)
            .autoconnect()
            .map { _ in Int.random(in: 1...100) } // Tasodifiy son

        // Subscriber β€” qiymatlarni qabul qiladi
        publisher
            .filter { $0 > 50 }           // Faqat 50 dan katta
            .map { "Son: \($0)" }          // String ga aylantirish
            .sink { matn in                 // Natijani olish
                print(matn)
            }
            .store(in: &cancellables)       // Subscription ni saqlash
    }
}


// ═══════════════════════════════════════
//  @PUBLISHED VA COMBINE
// ═══════════════════════════════════════
class QidiruvViewModel: ObservableObject {
    @Published var qidiruvMatni = ""
    @Published var natijalar: [String] = []
    private var cancellables = Set<AnyCancellable>()

    init() {
        // $qidiruvMatni β€” Combine Publisher
        $qidiruvMatni
            // 0.5 soniya kutish (debounce)
            .debounce(for: .seconds(0.5), scheduler: RunLoop.main)
            // Bo'sh matnni filtrlash
            .filter { !$0.isEmpty }
            // Avvalgi qidiruv bilan bir xil bo'lsa o'tkazib yuborish
            .removeDuplicates()
            // Natijani olish
            .sink { [weak self] matn in
                self?.qidirish(matn)
            }
            .store(in: &cancellables)
    }

    private func qidirish(_ matn: String) {
        // Tarmoq so'rovi...
        natijalar = ["Natija: \(matn)"]
    }
}

Combine Operatorlar

// ═══════════════════════════════════════
//  ASOSIY OPERATORLAR
// ═══════════════════════════════════════

// map β€” qiymatni o'zgartirish
[1, 2, 3].publisher
    .map { $0 * 10 }           // [10, 20, 30]

// filter β€” filtrlash
[1, 2, 3, 4, 5].publisher
    .filter { $0 > 3 }         // [4, 5]

// debounce β€” kutish (qidiruv uchun)
$matn.debounce(for: .seconds(0.3), scheduler: RunLoop.main)

// throttle β€” cheklash (scroll uchun)
$matn.throttle(for: .seconds(1), scheduler: RunLoop.main, latest: true)

// combineLatest β€” ikki publisher ni birlashtirish
$ism.combineLatest($email)
    .map { ism, email in
        !ism.isEmpty && email.contains("@")
    }
    .assign(to: &$formaTugri)

// flatMap β€” ichki publisher ga o'tish
$userId
    .flatMap { id in
        self.foydalanuvchiYukla(id: id)
    }

🎯 Topshiriq

Chat ilovasi yarating: WebSocket bilan ulanish, xabar yuborish/qabul qilish. Combine bilan $qidiruvMatni ga debounce(0.3) va removeDuplicates qo'llab, "yozmoqda..." indikatorini ko'rsating.

Buy mea coffee