Section 10/211 menit

10. Alur Data Lengkap

10. Alur Data Lengkap

Skenario: User membuka app, fetch users berhasil

swift
1. SceneDelegate.scene(_:willConnectTo:)
   └─ UserListConfigurator.makeViewController()
       └─ Semua komponen dibuat dan diwire

2. UserListViewController.viewDidLoad() [@MainActor]
   └─ fetchUsers()
       └─ Task { await interactor?.fetchUsers(request:) }
                                    
              Isolation boundary ───┼──────────────────────────
              @MainActor  actor    
                                    
3. UserListInteractor.fetchUsers(request:) [actor]
   ├─ guard !isLoading            cek atomic, aman
   ├─ isLoading = true            set atomic, aman
   ├─ await presenter?.presentLoading(true)
               
      boundary ┼── actor  @MainActor
               
      UserListPresenter.presentLoading(true) [@MainActor]
      └─ viewController?.displayLoading(true)
          └─ activityIndicator.startAnimating()   main thread
   
   ├─ let users = try await worker.fetchUsers()
               
      boundary ┼── actor(Interactor)  actor(Worker)
               
      UserWorker.fetchUsers() [actor]
      ├─ URLSession.data(for:)    network I/O, thread dilepas
      ├─ JSONDecoder.decode(...)   CPU work di background
      └─ return [User]            [User] adalah Sendable 
               
      kembali ke Interactor ─────┘
   
   ├─ cachedUsers = users          update state, aman (dalam actor)
   └─ await presenter?.presentUsers(response)
                
       boundary ┼── actor  @MainActor
                
4. UserListPresenter.presentUsers(_:) [@MainActor]
   ├─ map users  [DisplayedUser]   format string, di main thread
   └─ viewController?.displayUsers(viewModel)
                
                
5. UserListViewController.displayUsers(_:) [@MainActor]
   ├─ displayedUsers = viewModel.displayedUsers
   └─ tableView.reloadData()         UIKit di main thread

Skenario: User tap sebuah cell

swift
1. UITableViewDelegate.didSelectRowAt [:] [@MainActor]
   └─ Task { await interactor?.selectUser(request:) }
                                
              boundary ─────────┼── @MainActor  actor
                                
2. UserListInteractor.selectUser(request:) [actor]
   ├─ let user = cachedUsers[index]   aman (dalam actor)
   ├─ selectedUser = user             simpan untuk Router
   └─ await presenter?.presentSelectedUser(response)
                
       boundary ┼── actor  @MainActor
                
3. UserListPresenter.presentSelectedUser(_:) [@MainActor]
   └─ viewController?.displaySelectedUser(viewModel)
                
                
4. UserListViewController.displaySelectedUser(_:) [@MainActor]
   └─ router?.routeToUserDetail(userId:, userName:)
                
                
5. UserListRouter.routeToUserDetail(:) [@MainActor]
   ├─ buat UserDetailViewController
   └─ navigationController?.pushViewController(...)   UIKit di main thread