- Published on
SwiftUI crypto app — ViewModel va data service yordamida tangalarni yuklash
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
SwiftUI crypto app — ViewModel va data service yordamida tangalarni yuklash
Ushbu darsda biz nihoyat API orqali tarmoqdan real ma'lumotlarni yuklab olishni amalga oshiramiz. MVVM arxitekturasini kengaytirib, tarmoq so'rovlari va ma'lumotlarni yuklash vazifasini bajaruvchi CoinDataService nomli yangi servis (Service) qatlamini yaratamiz.
Ushbu servis Combine-ning Publisher (tarqatuvchi) imkoniyatlaridan foydalanadi. HomeViewModel esa ushbu servisga Subscriber (obunachi) bo'ladi va ma'lumot kelishi bilan uni qabul qilib ekranga uzatadi.
1. CoinDataService klassini yaratish
services papkasi ichida CoinDataService.swift nomli yangi fayl yaratamiz. Bu klass faqat ma'lumotlarni tarmoqdan yuklash, tekshirish va modelga o'tkazish (decoding) bilan shug'ullanadi:
import Foundation
import Combine
class CoinDataService {
// Tarmoqdan kelgan barcha tangalar ro'yxatini nashr qiluvchi (Publisher) o'zgaruvchi
@Published var allCoins: [CoinModel] = []
// Obunani (Subscription) saqlash va keyinchalik bekor qilish uchun o'zgaruvchi
private var coinSubscription: AnyCancellable?
init() {
getCoins()
}
private func getCoins() {
// API URL manzilini tekshiramiz
guard let url = URL(string: "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=250&page=1&sparkline=true&price_change_percentage=24h") else { return }
// URLSession yordamida Combine data task publisher yaratamiz
coinSubscription = URLSession.shared.dataTaskPublisher(for: url)
// So'rovni fondagi oqimda (Background Thread) bajarilishini ta'minlaymiz
.subscribe(on: DispatchQueue.global(qos: .default))
// Server javobini (HTTPResponse) va status kodini tekshiramiz
.tryMap { (output) -> Data in
guard let response = output.response as? HTTPURLResponse,
response.statusCode >= 200 && response.statusCode < 300 else {
throw URLError(.badServerResponse)
}
return output.data
}
// Ma'lumotlarni interfeysga uzatishdan oldin Asosiy oqimga (Main Thread) qaytamiz
.receive(on: DispatchQueue.main)
// JSON ma'lumotlarni [CoinModel] modeliga decode qilamiz
.decode(type: [CoinModel].self, decoder: JSONDecoder())
// Ma'lumotlarni qabul qilib olamiz
.sink(receiveCompletion: { (completion) in
switch completion {
case .finished:
break
case .failure(let error):
print("Ma'lumot yuklashda xatolik yuz berdi: \(error.localizedDescription)")
}
}, receiveValue: { [weak self] (returnedCoins) in
// Qabul qilingan tangalarni local array-ga joylaymiz
self?.allCoins = returnedCoins
// Bizga bu so'rov faqat bir marta kerak bo'lganligi uchun obunani bekor qilamiz
self?.coinSubscription?.cancel()
})
}
}
2. HomeViewModel-ni CoinDataService-ga obuna qilish
Endi home/viewmodels/HomeViewModel.swift fayliga o'tamiz. Ushbu ViewModel-da CoinDataService obyektini yaratamiz va undagi @Published var allCoins o'zgaruvchisiga obuna bo'lamiz:
import Foundation
import Combine
class HomeViewModel: ObservableObject {
@Published var allCoins: [CoinModel] = []
@Published var portfolioCoins: [CoinModel] = []
// Ma'lumotlar servisi obyekti
private let dataService = CoinDataService()
// ViewModel-dagi barcha obunalarni saqlash uchun to'plam
private var cancelables = Set<AnyCancellable>()
init() {
addSubscribers()
}
func addSubscribers() {
// Servisdagi allCoins publisher-ga obuna bo'lamiz
dataService.$allCoins
.sink { [weak self] (returnedCoins) in
// Servis ma'lumot olganida, biz ham o'z ro'yxatimizni yangilaymiz
self?.allCoins = returnedCoins
}
// Obunani to'plam ichida saqlab qolamiz
.store(in: &cancelables)
}
}
3. Kombayn (Combine) qanday ishlaydi
Combine zanjiri (pipeline) quyidagi tartibda ishlaydi:
- dataTaskPublisher: Ma'lumotni yuklashni boshlaydi (publisher).
- subscribe(on:): Bu operatsiyani fondagi oqimga (background thread) o'tkazadi.
- tryMap: Yuklangan ma'lumot to'g'ri kelganini tekshiradi (200-299 status kodlar).
- receive(on:): Qabul qilish jarayonini asosiy oqimga (main thread) qaytaradi.
- decode: Kelgan JSON formatdagi ma'lumotlarni biz yaratgan modelga moslab decode qiladi.
- sink: Xatolik yoki muvaffaqiyatli yakunlanishni kuzatadi hamda yakuniy natijani bizga yetkazadi.
Ushbu amallardan so'ng HomeView Canvas preview-sini qayta ishga tushirsangiz, internet orqali CoinGecko-dan 250 ta eng mashhur kriptovalyuta ma'lumotlari yuklanib ekranga chiqarilganini ko'rishingiz mumkin.
Keyingi darsda biz tarmoq so'rovini yanada toza va qayta ishlatiladigan (reusable networking layer) holatga keltiramiz! 🚀