Skip to content

g-enius/Fun-iOS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

239 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Fun - iOS Demo App

CI

A modern iOS application demonstrating clean architecture (MVVM-C), Swift Concurrency, modular design with Swift Package Manager, and best practices for scalable iOS development.

Three branches show progressive modernization:

Android counterpart: Fun-Android.

Screenshots

Home Detail Profile Settings
Home Detail Profile Settings

Demo

App Demo

Tech Stack & Branch Comparison

Three branches demonstrate progressive modernization β€” same app, three architectural approaches. Choose based on your minimum iOS target. All three produce visually identical apps.

main navigation-stack async-sequence
Best for iOS 15+ iOS 16+ iOS 17+
UI framework UIKit + SwiftUI SwiftUI 🚫 UIKit ← same
Reactive Combine ← same AsyncSequence 🚫 Combine
ViewModel ObservableObject + @Published ← same @Observable macro
View binding @ObservedObject ← same @Bindable / @State
Service events AnyPublisher + Subject ← same AsyncStream + StreamBroadcaster
Architecture MVVM + Coordinator ← same ← same
Coordinator β†’ ViewModel Closures ← same ← same
Language Swift 6.0 ← same ← same
DI Session-Scoped + @Service ← same ← same
LLM Foundation Models (iOS 26+) ← same ← same
Testing Swift Testing, swift-snapshot-testing ← same ← same

UIKit + SwiftUI vs Pure SwiftUI

Aspect main (UIKit + SwiftUI) navigation-stackΒ /Β async-sequenceΒ (PureΒ SwiftUI)
App entry point AppDelegate + SceneDelegate SwiftUI @main App
Tab bar UITabBarController subclass SwiftUI TabView
Navigation stack UINavigationController NavigationStack + NavigationPath
Push navigation pushViewController(_:animated:) path.append(item)
Modal presentation present(_:animated:) .sheet(isPresented:)
Views SwiftUI hosted in UIHostingController Native SwiftUI views
View controllers UIKit VCs wrap SwiftUI views None
Coordinators Multiple TabCoordinators Single AppCoordinator (ObservableObject)
Deep links scene(_:openURLContexts:) .onOpenURL { }
Transition control Full (UINavigationControllerDelegate) Limited (no custom transition API)

Known Behavioural Differences

The three branches are visually identical, but architectural differences produce minor behavioural variations:

Behaviour main (UIKit) navigation-stack / async-sequence (SwiftUI) Why
Items tab first load No loading spinner β€” data ready before tab appears Brief loading spinner on first tap UIKit coordinators are classes created eagerly at launch; SwiftUI view structs (and their @StateObject/@State ViewModels) are created lazily on first render
Share sheet position Bottom sheet (native UIActivityViewController) Popover anchored to toolbar button ShareLink in a ToolbarItem presents as a popover on iPhone β€” Apple controls this internally; no SwiftUI modifier can force bottom-sheet without import UIKit

Reactive State: Combine vs AsyncSequence

Aspect main / navigation-stack (Combine) async-sequence (AsyncSequence)
Service publisher AnyPublisher<Set<String>, Never> AsyncStream<Set<String>>
Multi-consumer CurrentValueSubject / PassthroughSubject StreamBroadcaster (custom, in Core)
Subscribe .sink { }.store(in: &cancellables) TaskΒ {Β forΒ awaitΒ valueΒ inΒ streamΒ {Β }Β }
Lifecycle cleanup Set<AnyCancellable> + cancellables = [] Task cancellation (task.cancel())
Debounced search .debounce(for:scheduler:) operator didSet + Task.sleep with cancellation
Initial value @Published emits on subscribe Read property directly, stream emits future changes
ViewModel observation ObservableObject
(per-object invalidation)
@Observable
(per-property tracking)

Module Structure

Fun-iOS/
β”œβ”€β”€ FunApp/         # iOS app target (Xcode project)
β”œβ”€β”€ Coordinator/    # Navigation coordinators
β”œβ”€β”€ UI/             # SwiftUI views & UIKit controllers
β”œβ”€β”€ ViewModel/      # Business logic (MVVM)
β”œβ”€β”€ Model/          # Data models & protocols
β”œβ”€β”€ Services/       # Concrete service implementations
└── Core/           # Utilities, DI container, L10n

All modules except FunApp are Swift packages. FunApp is the Xcode project that consumes them.

Dependency Hierarchy:

Modules only import from layers below them.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚               FunApp                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚          β”‚       Coordinator            β”‚
β”‚          β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Services β”‚            UI                β”‚
β”‚          β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚          β”‚         ViewModel            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                 Model                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                 Core                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Module Direct Dependencies
Core β€”
Model Core
ViewModel Model, Core
Services Model, Core
UI ViewModel, Model, Core
Coordinator UI, ViewModel, Model, Core
FunApp All 6

Key Patterns

MVVM + Coordinator

  • Model: Data models, protocols, domain logic
  • ViewModel: Business logic, state management
  • View: Pure UI (SwiftUI)
  • Coordinator: Navigation flow, screen transitions

Session-Scoped Dependency Injection

Each app flow gets its own session with a dedicated set of services. When the flow changes, the old session tears down and a fresh one activates β€” no stale state leaks between login and main.

LoginSession:         logger, network, featureToggles
AuthenticatedSession: logger, network, featureToggles, favorites, toast, ai
// Sessions activate/teardown automatically on flow transitions
protocol Session: AnyObject {
    func activate()   // register services
    func teardown()   // reset ServiceLocator
}

// ViewModels resolve lazily β€” no changes needed
@Service(.network) var networkService: NetworkService

Protocol-Oriented Design

All services defined as protocols in Model, implementations in Services.

Coordinator Hierarchy

AppCoordinator
β”œβ”€β”€ LoginCoordinator
β”œβ”€β”€ HomeCoordinator (detail + profile screens)
β”œβ”€β”€ ItemsCoordinator (detail screens)
└── SettingsCoordinator

3 tab coordinators handle all screens in their navigation stack directly. ViewModels communicate via closures (onShowDetail, onShowProfile, onPop, onShare, onDismiss, onLogin) β€” no coordinator protocols.

AppCoordinator manages login/main flow transitions with session lifecycle.

Deep Linking

URL scheme funapp:// for navigation:

  • funapp://tab/items - Switch to Items tab
  • funapp://item/swiftui - Open item detail
  • funapp://profile - Open profile

Test from terminal:

xcrun simctl openurl booted "funapp://tab/items"
xcrun simctl openurl booted "funapp://item/swiftui"
xcrun simctl openurl booted "funapp://profile"

Deep links received during login are queued and executed after authentication.

Features

  • Session-Scoped DI: Clean service lifecycle per app flow β€” no stale state
  • Reactive Data Flow: Combine framework with @Published properties
  • Feature Toggles: Runtime flags persisted via services
  • AI Summary: On-device LLM summarisation using Apple Intelligence / Foundation Models (iOS 26+)
  • Error Handling: Centralized AppError enum with toast notifications
  • Modern Search: Debounced input, loading states
  • Pull-to-Refresh: Native SwiftUI .refreshable
  • Dark Mode & Dynamic Type: System-adaptive colors, semantic font styles, System/Light/Dark appearance picker
  • iOS 17+ APIs: Symbol effects, sensory feedback (backwards compatible)

Testing

  • Unit Tests: ViewModels, services, and session lifecycle
  • Session DI Tests: Activation, teardown, transitions, state isolation
  • Snapshot Tests: Visual regression testing for all views
  • Parameterized Tests: Swift Testing with custom scenarios

Getting Started

Requirements

  • Xcode 16.0+
  • iOS 15.0+
  • Swift 6.0

Installation

git clone https://github.com/g-enius/Fun-iOS.git
cd Fun-iOS
open Fun.xcworkspace

Running

  1. Open Fun.xcworkspace
  2. Select FunApp scheme
  3. Choose simulator (iPhone 17 Pro recommended)
  4. Cmd + R to build and run

Tests

xcodebuild test -workspace Fun.xcworkspace -scheme FunApp \
  -destination 'platform=iOS Simulator,name=iPhone 17 Pro'

Code Quality

  • SwiftLint with strict rules (no force unwraps)
  • GitHub Actions CI (lint, build, test)
  • OSLog structured logging
  • SwiftGen for type-safe localization

AI-Assisted Development

This project demonstrates AI-assisted iOS development using Claude Code with project-level configuration for team-shareable guardrails, branch-aware rules, and custom workflows.

Claude Code Demo

Architecture and patterns designed by developer. Claude Code assists with feature implementation, bug fixes, testing, cross-platform parity checks, and code review β€” guided by project-level rules that enforce the architecture.

Commits with AI assistance include Co-Authored-By: Claude attribution.

Claude Code Project Configuration

.claude/
β”œβ”€β”€ settings.json                  # Team-shared permissions (auto-approve build/test/lint)
β”œβ”€β”€ skills/
β”‚   β”œβ”€β”€ review/SKILL.md            # /review β€” architecture + similar-pattern search
β”‚   β”œβ”€β”€ fix-issue/SKILL.md         # /fix-issue β€” end-to-end GitHub issue workflow
β”‚   β”œβ”€β”€ cross-platform/SKILL.md    # /cross-platform β€” iOS vs Android parity check
β”‚   β”œβ”€β”€ pull-request/SKILL.md      # /pull-request β€” draft PR with tests + accessibility
β”‚   └── sync/SKILL.md              # /sync β€” rebase feature branches onto main with AI conflict resolution
└── agents/
    └── change-reviewer.md         # Branch-aware code review agent
CLAUDE.md                          # Architecture rules, anti-patterns, build commands
ai-rules/
β”œβ”€β”€ general.md                     # MVVM-C patterns, DI, sessions, testing reference
β”œβ”€β”€ swift-style.md                 # Swift 6 concurrency, naming, reactive patterns
└── ci-cd.md                       # GitHub Actions CI workflow patterns

Branch-aware: Each branch has its own CLAUDE.md and ai-rules/ adapted for that branch's architecture. The change-reviewer agent knows which patterns to enforce β€” e.g., flagging import Combine on the async-sequence branch, or import UIKit on the SwiftUI branches.

Multi-branch workflow: Shared changes commit to main first, then feature branches rebase β€” enforced via project-level rules. The /sync skill and scripts/sync-branches.sh automate this: push main, rebase both feature branches, force-push, with retry logic for Xcode index.lock contention. When conflicts arise, /sync resolves them with AI.

Cross-platform: The /cross-platform skill compares iOS and Android implementations to catch unintentional UI/behavior divergences.


MIT License

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors