Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Simple repo showing how to implement the Coordinator pattern for handling navigation in a UIKit application with programmatic UI.

NotificationsYou must be signed in to change notification settings

Cooparr/CoordinatorExample

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 

Repository files navigation

A comprehensive iOS project demonstrating theCoordinator Pattern for navigation management in UIKit apps, including tab bar integration and child coordinators.

What is the Coordinator Pattern?

The Coordinator Pattern separates navigation logic from view controllers, making your code more:

  • Testable - Navigation logic can be unit tested independently
  • Reusable - View controllers don't know how they're presented
  • Maintainable - All navigation logic is centralized in coordinators
  • Flexible - Easy to change navigation flows without touching view controllers

Project Structure

CoordinatorExample/├── Coordinators/│   ├── MainCoordinator.swift          # Main tab navigation coordinator│   ├── LocationsCoordinator.swift     # Locations tab coordinator│   └── AccountCoordinator.swift       # Child coordinator for account flow├── ViewControllers/│   ├── TabBarViewController.swift     # Tab bar setup and coordinator management│   ├── MainViewController.swift       # Main tab content│   ├── LocationsViewController.swift  # Locations tab content│   ├── AccountViewController.swift    # Account screen (managed by child coordinator)│   ├── DetailViewController.swift     # Simple detail screen│   └── BottomSheetViewController.swift # Example modal presentation├── Models/│   └── User.swift                     # Example data model├── AppDelegate.swift└── SceneDelegate.swift               # App entry point

Key Features Demonstrated

✅ Tab Bar with Coordinators

  • Each tab has its own coordinator and navigation stack
  • Independent navigation flows per tab
  • Centralized tab bar configuration

✅ Child Coordinators

  • Complex flows managed by child coordinators
  • Automatic memory management and cleanup
  • Parent-child coordinator relationships

✅ Data Passing

  • Type-safe data injection through coordinators
  • Dynamic titles based on data
  • Proper dependency management

✅ Multiple Navigation Types

  • Push navigation within tabs
  • Modal presentation (bottom sheets)
  • Child coordinator navigation

✅ Navigation Bar Customization

  • Per-coordinator navigation bar styling
  • Large titles support
  • Custom appearance configurations

Architecture Overview

TabBarViewController├── MainCoordinator (Tab 1)│   ├── MainViewController│   ├── DetailViewController│   ├── BottomSheetViewController (modal)│   └── AccountCoordinator (child)│       └── AccountViewController└── LocationsCoordinator (Tab 2)    └── LocationsViewController

How It Works

1. App Launch & Tab Setup

// SceneDelegate creates the tab bar controllerwindow?.rootViewController=TabBarViewController()// TabBarViewController sets up coordinators for each tabclassTabBarViewController:UITabBarController{privatevarmainCoordinator:MainCoordinator?privatevarlocationsCoordinator:LocationsCoordinator?overridefunc viewDidLoad(){letmainNavController=UINavigationController()letlocationNavController=UINavigationController()                mainCoordinator=MainCoordinator(navigationController: mainNavController)        locationsCoordinator=LocationsCoordinator(navigationController: locationNavController)                // Configure tab items and start coordinators}}

2. Tab-Specific Navigation

// Each tab has its own coordinator managing its navigation stackclassMainCoordinator:NSObject,Coordinator,UINavigationControllerDelegate{func start(){letvc=MainViewController()        vc.mainCoordinator=self        vc.title="Main VC"        navigationController.pushViewController(vc, animated:false)}func showDetailViewController(){letvc=DetailViewController()        vc.mainCoordinator=self        vc.title="Some Detail VC"        navigationController.pushViewController(vc, animated:true)}}

3. Child Coordinator with Data

// Complex flows use child coordinatorsfunc showAccount(){letcurrentUser=getCurrentUser()letchild=AccountCoordinator(navigationController: navigationController)    child.parentCoordinator=self    childCoordinators.append(child)    child.start(user: currentUser)}

4. Automatic Memory Management

// Coordinators automatically clean up child coordinators when users navigate backfunc navigationController(_ navigationController:UINavigationController, didShow viewController:UIViewController, animated:Bool){    // Detect back navigation and cleanup child coordinatorsiflet accountViewController= fromViewControlleras?AccountViewController{childDidFinish(accountViewController.accountCoordinator)}}

Key Classes

Coordinator Protocol

protocolCoordinator:AnyObject{varchildCoordinators:[Coordinator]{getset}varnavigationController:UINavigationController{getset}}

TabBarViewController

  • Sets up tab bar with navigation controllers
  • Creates and manages top-level coordinators
  • Configures tab bar items and appearance

MainCoordinator

  • Manages navigation for the main tab
  • Demonstrates push navigation, modal presentation, and child coordinators
  • Custom navigation bar styling (white text on transparent background)

LocationsCoordinator

  • Manages navigation for the locations tab
  • Independent navigation stack from main tab
  • Different navigation bar styling (black text)

AccountCoordinator

  • Child coordinator demonstrating data passing
  • Takes aUser object via dependency injection
  • Managed by parent coordinator lifecycle

Navigation Examples

Push Navigation

func showDetailViewController(){letvc=DetailViewController()    vc.mainCoordinator=self    vc.title="Some Detail VC"    navigationController.pushViewController(vc, animated:true)}

Modal Presentation (Bottom Sheet)

func presentSomeBottomSheet(){letbottomSheetViewController=BottomSheetViewController()    bottomSheetViewController.mainCoordinator=self    bottomSheetViewController.modalPresentationStyle=.pageSheetiflet sheet= bottomSheetViewController.sheetPresentationController{        sheet.detents=[.medium(),.large()]        sheet.preferredCornerRadius=16        sheet.prefersGrabberVisible=true}        navigationController.present(bottomSheetViewController, animated:true)}

Child Coordinator with Data Injection

func showAccount(){letcurrentUser=getCurrentUser()letchild=AccountCoordinator(navigationController: navigationController)    child.parentCoordinator=self    childCoordinators.append(child)    child.start(user: currentUser)}// In AccountCoordinatorfunc start(user:User){letvc=AccountViewController(user: user)    vc.accountCoordinator=self    vc.title= user.name    navigationController.pushViewController(vc, animated:true)}

Memory Management

The project demonstrates proper memory management through:

  1. Strong coordinator references inTabBarViewController
  2. Weak coordinator references in view controllers
  3. Automatic child coordinator cleanup when navigating back
  4. Parent-child relationships preventing retain cycles
// TabBarViewController keeps coordinators aliveprivatevarmainCoordinator:MainCoordinator?privatevarlocationsCoordinator:LocationsCoordinator?// View controllers hold weak referencesweakvarmainCoordinator:MainCoordinator?weakvaraccountCoordinator:AccountCoordinator?

Data Models

User Model

structUser:Codable,Identifiable{private(set)varid=UUID()letname:Stringletemail:Stringletage:Int}

Used to demonstrate type-safe data passing between coordinators and dependency injection into view controllers.

Best Practices Demonstrated

  • Tab-specific navigation stacks - Each tab maintains independent navigation
  • Coordinator ownership - Tab bar controller owns top-level coordinators
  • Data flows through coordinators - No direct view controller communication
  • Centralized navigation configuration - All navigation logic in coordinators
  • Automatic memory management - Proper cleanup prevents memory leaks
  • Consistent patterns - Same approach for push, present, and child coordinators

Running the Project

  1. OpenCoordinatorExample.xcodeproj in Xcode
  2. Select your target device/simulator
  3. PressCmd + R to run

The app will launch with a tab bar containing:

  • Main Tab: Demonstrates push navigation, modals, and child coordinators
  • Locations Tab: Independent navigation stack with different styling

Requirements

  • iOS 15.0+
  • Xcode 14.0+
  • Swift 5.0+

Navigation Flows

Main Tab Flow

MainViewController├── DetailViewController (push)├── BottomSheetViewController (modal)└── AccountCoordinator    └── AccountViewController (with User data)

Locations Tab Flow

LocationsViewController└── (Additional location-specific navigation can be added)

Benefits Over Traditional Navigation

Traditional ApproachCoordinator Pattern
Navigation scattered across VCsNavigation centralized in coordinators
Tight coupling between screensLoose coupling through coordinator interface
Hard to test navigation flowsEasy to unit test coordinators
Difficult to change app flowEasy to modify flows in coordinators
Memory management issuesAutomatic coordinator cleanup
Mixed responsibilitiesClear separation of concerns

Extension Ideas

This project can be extended with:

  • More complex tab flows
  • Deep linking support
  • Navigation state restoration
  • Coordinator-based authentication flows
  • Custom transition animations
  • Universal link handling

This project serves as a comprehensive foundation for implementing the Coordinator Pattern in production iOS apps with tab bar navigation.

About

Simple repo showing how to implement the Coordinator pattern for handling navigation in a UIKit application with programmatic UI.

Topics

Resources

Stars

Watchers

Forks

Languages


[8]ページ先頭

©2009-2025 Movatter.jp