Coordinator: iOS navigatsiyasi uchun koordinator namunasining asosiy tushunchalari

Muallif: IT Sectr Nashr etilgan: 2026-02-18 O'qish vaqti: 9 daq

Coordinator (koordinator) — navigatsiyaning arxitektura namunasi bo'lib, ekranlar o'rtasidagi o'tish mantiqini ViewController-dan alohida sinflarga chiqaradi. Namuna 2015-yilda Soroush Khanlou tomonidan taklif qilingan va iOS hamjamiyatida keng tarqalgan. Coordinator ilovaning flow-ni boshqaradi: ViewController yaratadi va ko'rsatadi, ekranlar o'rtasida ma'lumot uzatadi va flow tugashini qayta ishlaydi. Namuna Massive View Controller muammosini hal qiladi, navigatsiyani kontrollerdan chiqaradi. Batafsil — Coordinator asl maqolasida.

Asosiy fikrlar

  • Coordinator — o'tish mantiqini ViewController-dan chiqaradigan navigatsiya namunasi
  • Mas'uliyat taqsimoti — ViewController UI-ni, Coordinator navigatsiyani boshqaradi
  • Router — UINavigationController abstraksiyasi uchun Coordinator-ning yordamchi komponenti
  • Flow — bir Coordinator tomonidan boshqariladigan ekranlar ketma-ketligi (masalan, onboarding)
  • Delegatsiya — bola koordinatorlari ota-onaga delegate/protocol orqali hisobot beradi

Coordinator nima: navigatsiya namunasining mohiyati

Coordinator — iOS ilovasida navigatsiya uchun mas'uliyatni o'z zimmasiga oladigan namuna. Standart UIKit-da ViewController o'tishlarni o'zi boshqaradi: present, push, show segue — barcha navigatsiya metodlari UIViewController-dan chaqiriladi. Coordinator bu mantiqni chiqaradi: ViewController hodisa haqida xabar beradi (masalan, „foydalanuvchi kirish tugmasini bosdi“), Coordinator keyingi qaysi ekranni ko'rsatishni hal qiladi. ViewController faqat UI mantiqi bilan qoladi va navigatsiyani koordinatorga topshiradi.

Namuna tuzilishi — start() va finish() metodlari bilan CoordinatorProtocol. start() — flow boshlanishi: birinchi ViewController yaratish va ko'rsatish. finish() — ota-ona koordinatoriga xabar berish bilan flow tugashi. Router — UINavigationController (yoki UISplitViewController) ustidagi qobiq, show, push, pop, dismiss metodlarini taqdim etadi. Koordinator to'g'ridan-to'g'ri UINavigationController bilan ishlamaydi — faqat Router orqali. Bu navigatsiyani test qilish va UI freymvorkini almashtirish imkonini beradi.

KomponentRolMisol
CoordinatorNavigatsiya flow-ni boshqarishAuthCoordinator, ProfileCoordinator
RouterUINavigationController ustidagi abstraksiyapush, present, pop, dismiss
ViewControllerUI + hodisalarni Coordinator-ga delegatsiya qilishLoginViewController.delegate

Coordinator hal qiladigan muammolar — Massive View Controller (navigatsiya — kontrollerning kengayishining keng tarqalgan sababi). Standart UIKit-da ViewController prepareForSegue, navigatsiya delegate-lari, unwind segues qayta ishlashni o'z ichiga oladi. Coordinator buni bartaraf qiladi. Storyboard-dagi Segue — ekranlar o'rtasida statik bog'lanish, Coordinator shartlar bilan dinamik navigatsiyani ta'minlaydi. Navigatsiyani test qilish mumkin bo'ladi: Coordinator-ni UI-siz, Router chaqiruvlari ketma-ketligini tekshirib test qilish mumkin.

Swift-da Coordinator: Router va Flow bilan amalga oshirish

Swift-da asosiy Coordinator — Router uchun bog'langan tur va start/finish metodlari bilan protokol. Router — UINavigationController-ni abstraksiya qiluvchi protokol. Router-ning aniq amalga oshirilishi UINavigationController-ni o'rab oladi va metodlarni unga topshiradi. Coordinator Router-ni init-da qabul qiladi va navigatsiya uchun foydalanadi. Bola koordinatorlari hayot aylanishini boshqarish uchun childCoordinators massivida saqlanadi.

swift
// Router — navigatsiya abstraksiyasi
protocol RouterProtocol: AnyObject {
    func push(_ viewController: UIViewController, animated: Bool)
    func pop(animated: Bool)
    func present(_ viewController: UIViewController, animated: Bool)
    func dismiss(animated: Bool)
}

final class NavigationRouter: RouterProtocol {
    private let navigationController: UINavigationController

    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }

    func push(_ vc: UIViewController, animated: Bool) {
        navigationController.pushViewController(vc, animated: animated)
    }

    func pop(animated: Bool) {
        navigationController.popViewController(animated: animated)
    }

    func present(_ vc: UIViewController, animated: Bool) {
        navigationController.present(vc, animated: animated)
    }

    func dismiss(animated: Bool) {
        navigationController.dismiss(animated: animated)
    }
}

// Coordinator — flow boshqaruvi
protocol CoordinatorProtocol: AnyObject {
    var childCoordinators: [CoordinatorProtocol] { get set }
    var router: RouterProtocol { get }
    func start()
    func finish()
}

class AuthCoordinator: CoordinatorProtocol {
    var childCoordinators: [CoordinatorProtocol] = []
    let router: RouterProtocol

    init(router: RouterProtocol) {
        self.router = router
    }

    func start() {
        let loginVC = LoginViewController()
        loginVC.onLogin = { [weak self] in
            self?.showHome()
        }
        router.push(loginVC, animated: true)
    }

    private func showHome() {
        let homeCoordinator = HomeCoordinator(router: router)
        childCoordinators.append(homeCoordinator)
        homeCoordinator.start()
    }

    func finish() {
        childCoordinators.removeAll()
        router.pop(animated: true)
    }
}

AppDelegate/SceneDelegate-da Coordinator yaratish — AppDelegate yoki SceneDelegate UINavigationController yaratadi, uni NavigationRouter-ga o'raydi, ildiz Coordinator (AppCoordinator) yaratadi va start() chaqiradi. AppCoordinator ilova holatiga qarab onboarding, kirish yoki asosiy ekranni ko'rsatishni hal qiladi. Coordinator — navigatsiya uchun yagona kirish nuqtasi, ViewController boshqa ekranlar haqida bilmaydi.

Bola Coordinator va koordinatorlar iyerarxiyasi

Koordinatorlar iyerarxiyasi — AppCoordinator → AuthCoordinator/MainCoordinator → ProfileCoordinator/SettingsCoordinator. Bola koordinatori ota-ona tomonidan yaratiladi va childCoordinators massivida saqlanadi. Bola koordinatori ishini tugatganda, ota-onada finish() chaqiradi va ota-ona uni childCoordinators-dan olib tashlaydi. Bu xotira oqishining oldini oladi: Coordinator ViewController-ga (Router orqali) kuchli havolaga ega va childCoordinators-dan olib tashlanmasa, obyekt bo'shatilmaydi.

swift
// Coordinator -> Parent aloqasi uchun Delegate
protocol AuthCoordinatorDelegate: AnyObject {
    func authCoordinatorFinished(_ coordinator: AuthCoordinator)
}

class AuthCoordinator: CoordinatorProtocol {
    weak var delegate: AuthCoordinatorDelegate?

    func finish() {
        delegate?.authCoordinatorFinished(self)
    }
}

// AppCoordinator — ota-ona
class AppCoordinator: AuthCoordinatorDelegate {
    func startAuthFlow() {
        let authCoordinator = AuthCoordinator(router: router)
        authCoordinator.delegate = self
        childCoordinators.append(authCoordinator)
        authCoordinator.start()
    }

    func authCoordinatorFinished(_ coordinator: AuthCoordinator) {
        childCoordinators.removeAll { $0 is AuthCoordinator }
        startMainFlow()
    }
}

childCoordinators-ni boshqarish — Coordinator-ni massivdan olib tashlash uni bo'shatishning yagona usuli. Tugallangan Coordinator-ni olib tashlashni unutib qo'ysangiz, u ViewController-lar bilan birga xotirada qoladi. Tavsiya etiladi: ota-onaning didMove(toParent:), tugatish callback-i yoki avtomatik olib tashlash uchun Combine publisher. Coordinator namunasi xabardor qilish mexanizmini spetsifikatsiya qilmaydi — delegate, closure yoki Combine — tanlov dasturchiga qoldiriladi.

Koordinatorlar o'rtasida ma'lumot uzatish usullari

Delegate orqali ma'lumot uzatish — bola Coordinator natijalar uzatiladigan metodlar bilan delegate protokolini belgilaydi: func authCoordinator(_:didLoginWith user: User). Ota-ona protokolni amalga oshiradi va bola flow tugashida ma'lumot oladi. Bu tur xavfsiz va ochiq-oydin. Kamchilik: har bir bola Coordinator uchun alohida protokol yozish kerak. 10+ Coordinator bo'lgan loyihalar uchun bu fayllar sonining ko'payishiga olib keladi.

Result turi orqali ma'lumot uzatish — finish metodi Result qabul qiladi, bu yerda Output flow natijasining umumiy turi. Coordinator — natijaning bog'langan turi bilan generik. Callback bilan start(): start(completion: @escaping (Output) -> Void). Bu kodni qisqartiradi: har bir koordinator uchun alohida protokol yozish shart emas. RxSwift/Combine: Coordinator natijani PassthroughSubject/Publisher orqali nashr etadi. Tanlov jamoaning arxitektura yondashuviga bog'liq.

UsulAfzalliklarKamchiliklar
DelegateTur xavfsiz, ochiq-oydin, alohida protokollarKo'p protokollar, ko'p boilerplate
ClosureKompakt, kam faylRetain cycle-ni tuzatish qiyin
Combine/RxReaktiv, oson birlashtirishKutubxonaga bog'liqlik, Debug qiyinroq

Umumiy ma'lumot qatlami — Coordinatorlar ma'lumotni to'g'ridan-to'g'ri uzatmaydi, balki umumiy xizmat/repozitoriydan foydalanadi. AuthCoordinator token-ni Keychain/UserDefaults-da saqlaydi, ProfileCoordinator u yerdan o'qiydi. Coordinatorlar umumiy holat (Dependency Injection konteyneri) orqali muloqot qiladi, to'g'ridan-to'g'ri chaqiruvlar bilan emas. Bu Coordinatorlar bog'liqligini kamaytiradi, lekin umumiy holatdan yashirin bog'liqliklarni yaratadi.

Coordinator-ni Router, VIPER va MVVM-C bilan solishtirish

Coordinator vs Router — Router UINavigationController-ni abstraksiya qiluvchi Coordinator komponenti. Coordinator flow uchun javobgar (qaysi ekranni ko'rsatish), Router — mexanika uchun (qanday ko'rsatish: push/present). Router „qanday“, Coordinator „nima“. Router-ni Coordinator-siz ishlatish mumkin (masalan, Navigator-singleton), lekin Coordinator Router-siz — shunchaki boshqa abstraksiya bilan ViewController. Odatda ikkala namuna birgalikda ishlatiladi.

Coordinator vs VIPER — VIPER navigatsiya uchun mas'ul bo'lgan Wireframe komponentiga ega — Coordinator analogi. VIPER-da Wireframe modulning bir qismi, Coordinator — modullar ustidagi alohida qatlam. VIPER moduli (View-Interactor-Presenter-Entity-Router) navigatsiyani modulning bir qismi sifatida o'z ichiga oladi. Coordinator modullarga nisbatan tashqi: modullarni yaratadi va bog'laydi, lekin ularning tarkibiga kirmaydi. Coordinator ekranlarni turli flow-larda qayta ishlatish uchun moslashuvchanroq.

MVVM-C — MVVM-ni Coordinator bilan kengaytirish. ViewModel to'g'ridan-to'g'ri Coordinator-ni bilmaydi — ViewController navigatsiyani ViewModel orqali topshiradi, ViewModel protokol orqali koordinatorni chaqiradi. MVVM-C — SwiftUI bilan iOS loyihalari uchun standart yondashuv: Coordinator NavigationStack yoki fullScreenCover-ni boshqaradi, ViewModel holatni nashr etish orqali koordinatorni chaqiradi. Apple SwiftUI uchun Coordinator-ni tavsiya etmaydi — NavigationStack va NavigationPath o'rnatilgan navigatsiya mexanizmlari.

swift
// MVVM-C: ViewModel protokol orqali Coordinator-ni chaqiradi
protocol AuthNavigationProtocol: AnyObject {
    func showMainScreen()
    func showForgotPassword()
}

class AuthViewModel: ObservableObject {
    weak var navigation: AuthNavigationProtocol?

    func loginTapped() {
        // mantiq...
        navigation?.showMainScreen()
    }
}

Ko'p beriladigan savollar

SwiftUI uchun Coordinator kerakmi?

SwiftUI uchun o'rnatilgan navigatsiya (NavigationStack, NavigationPath) ko'pincha Coordinator-ni almashtiradi. Apple path-based navigatsiyani tavsiya qiladi. Coordinator chuqur shartlarga ega murakkab flow-lar uchun ma'noga ega (roldan kelib chiqib onboarding-kirish-asosiy ekran). Oddiy SwiftUI ilovalari uchun Coordinator ortiqcha — NavigationPath dan foydalaning.

Coordinator Router-mi?

Yo'q, bu turli namunalar. Coordinator navigatsiya flow-ni boshqaradi: qaysi ekranni ko'rsatishni hal qiladi, ViewController yaratadi va ularni bog'laydi. Router — UINavigationController ustidagi abstraksiya: push, present, pop, dismiss. Coordinator navigatsiyani bajarish uchun Router-dan foydalanadi. Ba'zi amalga oshirishlarda Router Coordinator mantiqini o'z ichiga oladi (Router-per-screen), lekin bu asl namunadan chetlanishdir.

Coordinator-da retain cycle dan qanday qochish mumkin?

Ikkita asosiy oqish joyi: childCoordinators (ota-ona bolani ushlab, olib tashlashni unutadi) va Router (UINavigationController ViewController-ni ushlab turadi). Yechim: har doim bola Coordinator-ni finish() vaqtida massivdan olib tashlang. Delegate uchun weak havoladan foydalaning. Router uchun — UINavigationController-ga kuchli havola saqlamang, agar u allaqachon window iyerarxiyasida bo'lsa. Coordinator deinit-ni test qiling.

Coordinator qachon ortiqcha?

3-5 ekranli ilovalar uchun Coordinator ortiqcha — segue yoki oddiy navigationController.pushViewController soddaroq. NavigationStack bilan SwiftUI ilovalari uchun ham ortiqcha. Coordinator 15+ ekranli, murakkab flow-li (tarmoqlangan onboarding, parolni tiklash bilan avtorizatsiya) va aralash UIKit/SwiftUI loyihalari uchun asoslangan.

Coordinator-ni qanday test qilish kerak?

Mock Router — qaysi metodlar qanday parametrlar bilan chaqirilganini tekshirish. childCoordinators tekshiruvi: start() dan keyin massiv bo'sh emas, finish() dan keyin — bo'sh. Coordinator UI-siz test qilinadi: Router protokol, uning mock-i UIKit talab qilmaydi. Async flow uchun XCTestExpectation dan foydalaning. Android-da analog — NavigationController va NavHost-ni mock-navigatsiya bilan test qilish.

Xulosa

  • Coordinator — o'tishlarni ViewController-dan alohida sinfga chiqaradigan navigatsiya namunasi
  • Router — Coordinator tomonidan ishlatiladigan UINavigationController abstraksiyasi
  • Iyerarxiya — ota-ona va bola Coordinator natijalarni delegatsiya qilish bilan
  • MVVM-C — UIKit loyihalari uchun Coordinator bilan standart yondashuv
  • SwiftUI — NavigationStack orqali o'rnatilgan navigatsiya Coordinator-ni almashtiradi
  • Test qilish — Coordinator UIKit-siz mock Router orqali test qilinadi

Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz

IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.

Loyihani muhokama qilish

Shuningdek o'qing