Router — مبانی الگوی مسیریابی در iOS و Android

نویسنده: IT Sectr منتشر شده: 2026-02-19 زمان مطالعه: 9 دقیقه

Router (مسیریاب) — الگوی معماری که منطق ناوبری بین صفحات برنامه را متمرکز می‌کند. Router تعیین می‌کند هنگام وقوع رویداد به کجا و چگونه منتقل شود. در iOS، Router UINavigationController و segue را انتزاع می‌کند، در Android — FragmentManager و NavController از Jetpack Navigation. Router می‌تواند به عنوان یک الگوی مستقل یا به عنوان یک جزء Coordinator (Router-per-Coordinator) و VIPER (Router-per-module) کار کند. بیشتر — در Android Navigation Component Guide.

نکات اصلی

  • Router — الگوی مسیریابی که ناوبری بین صفحات را متمرکز می‌کند
  • دو سطح — Router می‌تواند جزء Coordinator یا یک الگوی مستقل باشد
  • iOS Router — انتزاع بر روی UINavigationController با متدهای push/present/pop
  • Android Router — Jetpack Navigation Component با NavController و deep links
  • URL Routing — مسیریابی بر اساس طرح‌های URL (deeplink, universal link)

Router چیست: ماهیت الگوی مسیریابی

Router — الگویی که منطق انتقال بین صفحات را کپسوله می‌کند. ایده اصلی: ViewController (یا Presenter/ViewModel) مستقیماً navigationController.pushViewController را فراخوانی نمی‌کند، بلکه قصد انتقال خود را به Router اطلاع می‌دهد. Router تصمیم می‌گیرد کدام ViewController ایجاد شود و چگونه نمایش داده شود. Router می‌تواند ساده (مجموعه‌ای از متدهای ناوبری) یا پیچیده (با مسیریابی بر اساس طرح‌های URL، deep link‌ها و اعلان‌های push) باشد.

سه رویکرد به Router — Router به عنوان سرویس (Navigator-singleton سراسری)، Router به عنوان جزء ماژول (رویکرد VIPER)، Router به عنوان پروتکل (انتزاع برای Coordinator). Router سراسری — سادگی (یک نمونه برای کل برنامه) — در پروژه‌های کوچک محبوب است. Router ماژولار — هر ویژگی Router مخصوص خود را دارد — استاندارد VIPER و Clean Architecture. Router پروتکلی — در Coordinator استفاده می‌شود: RouterProtocol با متدهای push/present/pop/dismiss.

رویکردساختارزمان استفاده
Navigator سراسریSingleton با متدهای انتقالپروژه‌های کوچک، نمونه‌های اولیه
Router ماژولارRouter درون هر ماژولVIPER, Clean Architecture
Router پروتکلیProtocol + پیاده‌سازی برای CoordinatorMVVM-C, Coordinator pattern

تاریخچه الگو — Router در فریم‌ورک‌های وب (URL Router — Rails Routes, Express.js) ظهور کرد و برای توسعه موبایل تطبیق داده شد. در iOS، Router با رشد VIPER (2015-2017) محبوب شد. در Android، Router — بخشی از Jetpack Navigation (2018)، راه‌حل استاندارد Google برای ناوبری است. اکنون Router بخش جدایی‌ناپذیر هر معماری ماژولار برنامه‌های موبایل است.

Router در iOS: پیاده‌سازی در Swift

iOS Router — پروتکلی با متدهایی برای انواع مختلف ناوبری. پیاده‌سازی پایه UINavigationController را می‌پوشاند. Router می‌تواند ارائه‌های modal (present/dismiss)، push/pop در پشته ناوبری، showDetail برای Split View Controller و ارائه‌های تمام‌صفحه (iOS 13+) را مدیریت کند. Router ViewController ایجاد نمی‌کند — نمونه آماده دریافت می‌کند و آن را نمایش می‌دهد. ایجاد ViewController توسط کارخانه (Assembly، DI-container) یا Coordinator انجام می‌شود.

swift
// RouterProtocol برای iOS
protocol RouterProtocol {
    func push(_ viewController: UIViewController, animated: Bool)
    func pop(animated: Bool)
    func popToRoot(animated: Bool)
    func present(_ viewController: UIViewController, animated: Bool)
    func dismiss(animated: Bool)
    func setViewControllers(_: [UIViewController], animated: Bool)
}

// پیاده‌سازی Router از طریق UINavigationController
class NavigationRouter: RouterProtocol {
    private let navigationController: UINavigationController

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

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

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

    func popToRoot(animated: Bool) {
        navigationController.popToRootViewController(animated: animated)
    }

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

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

    func setViewControllers(_ vcs: [UIViewController], animated: Bool) {
        navigationController.setViewControllers(vcs, animated: animated)
    }
}

// Assembly — ایجاد ماژول با Router
protocol ProfileModuleFactory {
    func makeProfileView() -> UIViewController
}

Router در VIPER — هر ماژول VIPER Router مخصوص خود را دارد که می‌داند از ماژول جاری کدام صفحات باز شوند. Router ViewController ماژول بعدی را از طریق کارخانه ایجاد می‌کند و کنترل را منتقل می‌کند. Router در VIPER — تنها مؤلفه‌ای است که import UIKit دارد (به جز View). این کار آزمایش Presenter و Interactor را آسان می‌کند: آنها به UIKit وابسته نیستند.

Router در Android: Jetpack Navigation Component

Jetpack Navigation Component — روتر استاندارد برای Android که از سال 2018 توسط Google توصیه می‌شود. ناوبری در گراف XML (nav_graph.xml) تعریف می‌شود: گره‌ها (fragments, activities, destinations) و یال‌ها (actions). NavController انتقال‌ها را مدیریت می‌کند: FragmentManager.replace/add را فراخوانی کرده و back stack را مدیریت می‌کند. Navigation Component از deep link‌ها، آرگومان‌ها، انیمیشن‌های انتقال و Safe Args برای انتقال نوع‌امن داده پشتیبانی می‌کند.

kotlin
// nav_graph.xml — گراف ناوبری
<!-- @xml/nav_graph.xml -->
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_graph"
    app:startDestination="@id/loginFragment">

    <fragment android:id="@+id/loginFragment"
        android:name=".ui.login.LoginFragment">
        <action android:id="@+id/to_home"
            app:destination="@id/homeFragment" />
    </fragment>

    <fragment android:id="@+id/homeFragment"
        android:name=".ui.home.HomeFragment">
        <argument android:name="userId"
            android:defaultValue="0"
            app:argType="integer" />
        <deepLink app:uri="myapp://home/{userId}" />
    </fragment>
</navigation>

// Kotlin — ناوبری از طریق NavController
class LoginFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding.loginButton.setOnClickListener {
            val action = LoginFragmentDirections.toHome(userId = 42)
            findNavController().navigate(action)
        }
    }
}

// Safe Args — آرگومان‌های نوع‌امن
class HomeFragmentArgs : NavArgs {
    val userId: Int get() = arguments?.getInt("userId") ?: 0
}

// NavigationUI — ادغام با Toolbar, BottomNav, Drawer
class MainActivity : AppCompatActivity() {
    private lateinit var navController: NavController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val navHost = supportFragmentManager
            .findFragmentById(R.id.nav_host_fragment) as NavHostFragment
        navController = navHost.navController
        NavigationUI.setupActionBarWithNavController(this, navController)
    }
}

Deep links در Android Navigation — Navigation Component از deep link‌های صریح (PendingIntent + NavDeepLinkBuilder) و ضمنی (از طریق intent-filter در مانیفست) پشتیبانی می‌کند. Deep link می‌تواند به هر گره nav_graph منتهی شود. پردازش اعلان‌های push: Notification یک PendingIntent با NavDeepLinkBuilder ایجاد می‌کند که back stack را بازیابی کرده و صفحه مورد نظر را باز می‌کند. Navigation Component به طور خودکار دکمه‌های Up/Back را مدیریت کرده و کاربر را به صفحه قبلی بازمی‌گرداند.

URL Routing: مسیریابی Deeplink و Universal Link

URL Routing — مسیریابی بر اساس طرح‌های URL، deep link‌ها و universal link‌ها. برنامه یک طرح (myapp://profile/42) یا universal link (https://example.com/profile/42) را ثبت می‌کند. Router URL را تجزیه می‌کند، پارامترها را استخراج می‌کند (userId=42) و صفحه مربوطه را باز می‌کند. URL Routing امکان باز کردن برنامه از خارج را فراهم می‌کند: از طریق لینک وب‌سایت، ایمیل، اعلان push، کد QR. iOS از NSUserActivity + universal link استفاده می‌کند، Android — intent-filter + deep link.

swift
// URL Router — تجزیه deep link و ناوبری
protocol URLRoute {
    var pattern: String { get }
    func navigate(parameters: [String: String], router: RouterProtocol)
}

struct ProfileRoute: URLRoute {
    let pattern = "myapp://profile/{userId}"

    func navigate(parameters: [String: String], router: RouterProtocol) {
        guard let userId = parameters["userId"] else { return }
        let profileVC = ProfileViewController(userId: userId)
        router.push(profileVC, animated: true)
    }
}

// URL Router — تطبیق URL با مسیرها
class URLRouter {
    private var routes: [URLRoute] = []

    func handle(_ url: URL, router: RouterProtocol) {
        for route in routes {
            if let params = matchPattern(route.pattern, url: url) {
                route.navigate(parameters: params, router: router)
                return
            }
        }
    }
}

Deep link routing در عمل — برنامه باید deep link را در سه حالت پردازش کند: اجرا نشده (راه‌اندازی با deep link)، در پس‌زمینه (بازیابی از پس‌زمینه)، فعال (onNewIntent/SceneDelegate). URL Router باید back stack را به درستی بازیابی کند: در deep link به صفحه پروفایل، کاربر باید بتواند Back را فشار داده و به صفحه قبلی بازگردد. iOS و Android back stack را متفاوت مدیریت می‌کنند — Router باید ویژگی‌های پلتفرم را در نظر بگیرد.

مقایسه Router با Coordinator و Navigator

Router vs Coordinator — Router به سوال "چگونه صفحه را نمایش دهیم؟" پاسخ می‌دهد (push/present)، Coordinator — "کدام صفحه را نمایش دهیم؟" (کدام flow را اجرا کنیم). Router ابزار ناوبری است، Coordinator سازمان‌دهنده flow. Router توسط Coordinator استفاده می‌شود. در VIPER، Router هر دو عملکرد را انجام می‌دهد: تصمیم می‌گیرد به کجا برود و چگونه نمایش دهد. در MVVM-C، Router — یک پروتکل جداگانه است که توسط Coordinator استفاده می‌شود. الگوها یکدیگر را حذف نمی‌کنند، بلکه مکمل هم هستند.

ویژگیRouterCoordinatorNavigator
تمرکزمکانیک ناوبریFlow ناوبریدسترسی سراسری
سطحUI-framework (push/present)منطق کسب و کار (flow)زیرساخت
ایجاد صفحاتVC آماده دریافت می‌کندVC را از طریق کارخانه ایجاد می‌کندVC ایجاد می‌کند
چرخه حیاتیکی برای هر ناوبریchildCoordinatorsSingleton

Router vs Navigator — Navigator — نام قدیمی Router در جامعه iOS. در پیاده‌سازی‌های اولیه، Navigator یک کلاس Singleton با متدهای انتقال بود. Navigator — یک Router-singleton سراسری است. Navigator ساده‌تر است، اما وابستگی‌های پنهان ایجاد می‌کند. Router مبتنی بر پروتکل — قابل آزمایش‌تر و ماژولارتر است. Navigator برای پروژه‌های بدون معماری سخت‌گیرانه مناسب است، Router — برای Clean Architecture و VIPER.

سوالات متداول

تفاوت بین Router و Coordinator چیست؟

Router — انتزاع بر روی UINavigationController (push/present/pop). Coordinator — لایه‌ای بر روی Router که flow را مدیریت می‌کند (کدام صفحه بعدی نمایش داده شود). Router مسئول مکانیک است، Coordinator — مسئول منطق ناوبری. Coordinator از Router برای انجام انتقال‌ها استفاده می‌کند. در VIPER، Router هر دو عملکرد را ترکیب می‌کند، در MVVM-C — جدا شده‌اند.

آیا استفاده از Router در برنامه موبایل ضروری است؟

خیر. برای برنامه‌های با 3-5 صفحه، فراخوانی مستقیم navigationController.pushViewController یک راه‌حل عادی است. Router با 10+ صفحه، deep link‌ها، اعلان‌های push و معماری ماژولار مفید می‌شود. Router آزمایش ناوبری را ساده می‌کند و امکان پردازش متمرکز انتقال‌ها از هر منبع (دکمه، deep link، push) را فراهم می‌کند.

Router چگونه با Deep Links مرتبط است؟

URL Router — extension Router که deep link‌ها و universal link‌ها را تجزیه می‌کند. URL Router تطابق بین URL و صفحه برنامه را تعیین می‌کند. به عنوان مثال، route myapp://profile/42 → ProfileViewController(userId: 42). URL Router پردازش deep link‌ها را از منابع مختلف متمرکز می‌کند: اعلان‌های push، کدهای QR، لینک‌های ایمیل، لینک‌های جهانی.

آیا می‌توان از Router بدون Coordinator استفاده کرد؟

بله. Router می‌تواند مستقل عمل کند — به عنوان Navigator سراسری یا به عنوان جزء ماژول VIPER. Router بدون Coordinator — صرفاً کپسوله‌سازی UINavigationController پشت یک پروتکل است. Coordinator بدون Router — سخت‌تر است (ViewController خود push/present را فراخوانی می‌کند)، اما ممکن است. بهترین روش — Router + Coordinator با هم.

Router در Android همان iOS Router است؟

از نظر عملکردی — بله، هر دو ناوبری را متمرکز می‌کنند. پیاده‌سازی متفاوت است: iOS Router — پروتکل + کلاس در اطراف UINavigationController؛ Android — Jetpack Navigation Component با گراف XML و NavController. Android Router در فریم‌ورک تعبیه شده است (Navigation Component)، iOS Router — پیاده‌سازی خارجی. Android Router از Safe Args پشتیبانی می‌کند، iOS Router — خیر (نیاز به generics یا Codable دارد).

خلاصه

  • Router — الگوی مسیریابی که منطق انتقال بین صفحات را کپسوله می‌کند
  • iOS Router — پروتکل با متدهای push/present/pop در اطراف UINavigationController
  • Android Router — Jetpack Navigation Component با XML nav_graph و NavController
  • URL Routing — مسیریابی از طریق deep link‌ها و لینک‌های جهانی
  • Router vs Coordinator — Router مسئول مکانیک است، Coordinator مسئول flow ناوبری
  • کاربرد — معماری ماژولار، deep link‌ها، آزمایش ناوبری

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید