Created
August 13, 2023 08:26
-
-
Save aduuub/56911fa6313fede348fd236910cccd26 to your computer and use it in GitHub Desktop.
Generic ViewModel
This file contains 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
// | |
// TestViewModel.swift | |
// Test | |
// | |
// Created by Adam Wareing on 11/8/2023. | |
// | |
import UIKit | |
/// Model for storing a section and its contents | |
struct SectionDTO<Section, Item> { | |
var section: Section | |
var content: [Item] = [] | |
} | |
/// Generic view model that stores a list of sections and their data | |
class ViewModel<SectionIdentifierType: Hashable, ItemIdentifierType: Hashable> { | |
typealias Section = SectionDTO<SectionIdentifierType, ItemIdentifierType> | |
var sections: [Section] = [] | |
func build(@ViewModelBuilder<Section> _ builder: () -> [Section]) { | |
self.sections = builder() | |
} | |
func section(_ section: SectionIdentifierType, @ViewModelBuilder<ItemIdentifierType> _ builder: () -> [ItemIdentifierType]) -> Section { | |
Section(section: section, content: builder()) | |
} | |
func snapshot() -> NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType> { | |
var snapshot = NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>() | |
// Add sections | |
snapshot.appendSections(sections.map { $0.section }) | |
// Add items | |
sections.forEach { model in | |
snapshot.appendItems(model.content, toSection: model.section) | |
} | |
return snapshot | |
} | |
func debugString() -> String { | |
sections.reduce("", { | |
$0 + "\($1.section) section: \($1.content)" | |
}) | |
} | |
} | |
/// Result builder for constructing section items | |
@resultBuilder | |
struct ViewModelBuilder<T> { | |
static func buildEither(first component: [T]) -> [T] { | |
return component | |
} | |
static func buildEither(second component: [T]) -> [T] { | |
return component | |
} | |
static func buildOptional(_ component: [T]?) -> [T] { | |
return component ?? [] | |
} | |
static func buildExpression(_ expression: T) -> [T] { | |
return [expression] | |
} | |
static func buildExpression(_ expression: ()) -> [T] { | |
return [] | |
} | |
static func buildBlock(_ components: [T]...) -> [T] { | |
return components.flatMap { $0 } | |
} | |
static func buildArray(_ components: [[T]]) -> [T] { | |
Array(components.joined()) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment