Skip to content

Instantly share code, notes, and snippets.

@robertvunabandi
Created November 18, 2025 05:05
Show Gist options
  • Select an option

  • Save robertvunabandi/3ee16d5adc0d421d1de57a6c4c52aacb to your computer and use it in GitHub Desktop.

Select an option

Save robertvunabandi/3ee16d5adc0d421d1de57a6c4c52aacb to your computer and use it in GitHub Desktop.
//
// AuthorsDataStore.swift
// Reading Journal
//
//
import SwiftUI
final class AuthorsDataStore: SingleInstanceDataStore {
typealias Fetcher = AuthorsDataFetcher
static let Enum = DataType.authors
// Instance variables that need to be initialized
@Published
private var user: MUser
private init(user: MUser) {
self.user = user
}
// Other instance variables
@Published
private(set) var authors: [MAuthor] = []
// Static variables
private static let LOG = Tools.getLogger(filename: #file)
}
// MARK: Implementing DataStore Protocol Methods
extension AuthorsDataStore {
private static var INSTANCE: AuthorsDataStore?
static func shared(_ user: MUser) -> Self {
if INSTANCE == nil {
INSTANCE = AuthorsDataStore(user: user)
}
return INSTANCE! as! Self
}
static func flush() {
LOG.info("Flushing \(String(describing: self))", #line)
INSTANCE = nil
}
func seed(_ seeding: DataStoreSeeding) {
switch seeding {
case let .author(author):
add(author: author)
default: ()
}
}
}
// MARK: Product Accessors
extension AuthorsDataStore {
func by(id: String) -> MAuthor? {
authors.first { $0.id == id }
}
/// Returns whether there exists an author with the given name
/// - Parameter name: Author's name to check
/// - Returns: `true` if an author with a matching name exists in this data store
func exists(with name: String) -> Bool {
authors.contains {
$0.name.lowercased() == name.lowercased()
}
}
}
// MARK: Fetcher Accessors
// Product shouldn't call these methods directly.
extension AuthorsDataStore {
func add(author: MAuthor) {
withAnimation(.easeInOut(speed: .xFast)) {
addImpl(author: author)
}
}
func add(authors: [MAuthor]) {
withAnimation(.easeInOut(speed: .xFast)) {
authors.forEach { addImpl(author: $0) }
}
}
func update(author: MAuthor) {
withAnimation(.easeInOut(speed: .xFast)) {
updateImpl(author: author)
}
}
func remove(author: MAuthor) {
withAnimation(.easeInOut(speed: .xFast)) {
authors.removeAll { $0.id == author.id }
}
}
}
// MARK: Private Methods
extension AuthorsDataStore {
private func addImpl(author: MAuthor) {
sortAfter {
if by(id: author.id) != nil {
updateImpl(author: author)
return
}
authors.append(author)
}
}
private func updateImpl(author: MAuthor) {
sortAfter {
guard let index = firstIndexOf(author) else {
return
}
authors[index] = author
}
}
private func firstIndexOf(_ author: MAuthor) -> Int? {
authors.firstIndex { $0.id == author.id }
}
private func sortAfter(callable: () -> Void) {
callable()
authors.sort(using: MAuthor.nameComparator())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment