[iOS] Akash — PokéDex Assignment#6
Open
akashkahalkar wants to merge 31 commits into
Open
Conversation
added xcode project. created koinRepository manager
handles image fetch handles caching handles retry mechanism
completed integration with view model fixed Ui glitches. added compatibility with dark mode
added view for empty treatment
used environment to inject view model factory used viewModel factory to create the viewmodels
added type chip view added stats view added type color helper
changed color pallete for stats view updated padding for stats title
broken into smaller components
updated factory to create favorite view model
on favorite click user gets a feedback
cosmetics changes to the details view
added test cases for view model, formatter and flow collector
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
[iOS] Akash — PokéDex Assignment
Overview
A Pokédex app UI using Swift-UI integrating the provided KMP shared module. Covers Pokémon listing with infinite scroll and search, a detail screen, and a persistent favourites tab — all wired to the KMP layer through a clean, lifecycle-safe Store architecture.
Screenshots / Screen Recording
light.mov
dark.mov
Implementation Decisions
ViewModelFactory + SwiftUI Environment DI
A
ViewModelFactoryprotocol drives all ViewModel creation and is injected into the view tree via a custom SwiftUIEnvironmentKey:Views request ViewModels through
@Environment(\.viewModelFactory)rather than constructing them directly. This keeps the dependency flow strictly top-down, avoids singletons in views, and makes every screen independently testable by swapping in a mock factory.AppDependenciesimplements the factory and holds the singlePokemonRepositoryresolved from Koin at startup.StateFlow → Swift Concurrency Bridge
A
StateFlowCollectorwrapsKotlinx_coroutines_coreFlowCollectorand exposes a typedAsyncStreamextension, letting every Store write clean structured-concurrency loops:Each Store syncs the current
StateFlowvalue synchronously oninitcallsviewModel.onCleared()indeinitto release Kotlin coroutine scopes.Koin DI from Swift
Because Koin's reified
get<T>()doesn't cross the Kotlin/Native boundary,KoinDependencyManagerresolvesPokemonRepositoryby iteratingkoin.instanceRegistry.instancesand matching onqualifiedName, then callingkoin.get(clazz:qualifier:parameters:)with the resolvedKotlinKClass.Haptic Feedback
A protocol-based
HapticsManager(HapticsProviding) fires aUINotificationFeedbackGenerator(.success)pulse when a Pokémon is added to favourites. The protocol is injected intoDetailsViewas a default parameter, making the haptics trivially mockable in tests without any extra setup.Deleting Favourites
The Favourites screen is reactively driven by
FavouritesViewModel, which observes the KMPFavoritesViewModel.favoritesStateFlow(backed by SQLDelight). Removing a Pokémon is exposed as a trailing swipe action with full-swipe support:unfavouritecallsrepository.setFavorite(isFavorite: false)on the KMP layer — the SQLDelight-backed flow emits the updated list automatically, so no manual state refresh is needed.Screens
LazyVGrid, infinite scroll,.searchable, pull-to-refresh, empty/error statesNavigation uses a
TabView(Pokédex / Favourites) with each tab owning its ownNavigationStack. Detail is pushed viaNavigationLinkusing the factory closure injected at the call site.Known Limitations & Future Improvements
qualifiedNamestring match breaks if the shared module package is renamed. AKoinHelper.ktshim in the shared module would be the clean fix.StateFlowCollectorbridge and provide exhaustiveswitchon sealed classes automatically.