https://github.com/hudishkin/vvsi
Lightweight architecture for SwiftUI application. Something between TCA and MVVM.
https://github.com/hudishkin/vvsi
architecture ios-architecture mvvm swift swiftui tca
Last synced: about 1 year ago
JSON representation
Lightweight architecture for SwiftUI application. Something between TCA and MVVM.
- Host: GitHub
- URL: https://github.com/hudishkin/vvsi
- Owner: hudishkin
- License: mit
- Created: 2025-02-16T16:04:29.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-05-05T10:27:50.000Z (about 1 year ago)
- Last Synced: 2025-05-05T11:38:16.010Z (about 1 year ago)
- Topics: architecture, ios-architecture, mvvm, swift, swiftui, tca
- Language: Swift
- Homepage:
- Size: 50.8 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# View - ViewState - Interactor (VVSI)
VVSI is an experimental (very) simple architecture for SwiftUI applications, representing something between [TCA](https://github.com/pointfreeco/swift-composable-architecture) (The Composable Architecture) and [MVVM](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel). The library offers a structured and predictable approach to managing state and business logic, while maintaining ease of use.
## 📊 Architecture Diagram

## 🌟 Benefits
- **Separation of concerns** — clear separation of UI, state, and business logic
- **Predictable data flow** — unidirectional data flow makes the application more stable
- **Testability** — isolated components are easy to test
- **Out-of-the-box asynchronicity** — support for asynchronous operations using Swift Concurrency
- **Native SwiftUI integration** — works naturally with the SwiftUI system
## 📦 Installation
### Swift Package Manager
```swift
dependencies: [
.package(url: "https://github.com/username/VVSI.git", from: "0.0.5")
]
```
## 🚀 How to Use
VVSI consists of three main components:
1. **View** — responsible for UI and state display
2. **ViewState** — stores the current state and processes actions
3. **Interactor** — contains business logic and handles side effects
### Example: Simple List
#### 1. Create state and action components
```swift
// ListView+State.swift
extension ListView {
struct Options {
let count: Int
let length: Int
}
struct VState: StateProtocol {
var items: [String] = []
}
enum VAction: ActionProtocol {
case add
case remove
case random(Options)
}
enum VNotification: NotificationProtocol {
case error(String)
}
}
```
#### 2. Implement the interactor to handle business logic
```swift
// ListView+Interactor.swift
extension ListView {
final class Interactor: ViewStateInteractorProtocol {
typealias S = VState
typealias A = VAction
typealias N = VNotification
let notifications: PassthroughSubject = .init()
let service: Dependencies.Service
init(dependencies: Dependencies = .shared) {
service = dependencies.service
}
@MainActor
func execute(
_ state: @escaping CurrentState,
_ action: VAction,
_ updater: @escaping StateUpdater
) {
switch action {
case .add:
Task.detached { [weak self] in
guard await state().items.count < 5 else {
self?.notifications.send(.error("Max items count is 5"))
return
}
await updater { state in
state.items.append("New item")
}
}
case .remove:
Task.detached {
await updater { state in
if !state.items.isEmpty {
state.items.removeLast()
}
}
}
case .random(let opt):
Task {
let strings = (0..