Last active
September 12, 2019 20:19
-
-
Save PaulWoodIII/ddf58a823f3ff0b99c582b16f5f2047c to your computer and use it in GitHub Desktop.
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
import Foundation | |
class Box<T> { | |
typealias Observer = (T) -> Void | |
var observer: Observer? | |
func bind(observer: Observer?) { | |
self.observer = observer | |
} | |
var value: T { | |
didSet { | |
observer?(value) | |
} | |
} | |
init(_ v: T) { | |
value = v | |
} | |
} | |
// Reference type at the Obj-C level for persistence | |
public class HeroMO: NSObject { | |
var id = UUID() | |
var name: String = "" | |
var organization: OrganizationMO? | |
} | |
// Reference type at the Obj-C level for persistence | |
class OrganizationMO: NSObject { | |
var id = UUID() // basically a NSManagedObjectID | |
var name: String = "" | |
var heros: Set<HeroMO> = [] | |
} | |
class UniverseMO: NSObject { | |
} | |
public class HeroDatabase: NSObject { | |
// using a dictionary because it ensures the uniqueness of Heros by name | |
// this is the source of truth and could be considered the result of a fetch request | |
private var allHeros = [String: HeroMO]() | |
// using a dictionary because it ensures the uniqueness of Organizations by name | |
// this is a source of truth and could be considered the result of a fetch request | |
private var allOrganizations = Dictionary<String,OrganizationMO>() | |
private var ordering: Array<UUID> = [] { | |
didSet { | |
arrangeHeros() | |
} | |
} | |
// source of truth from the Views Perspective | |
var displayItems: Box<ComicbookCharacters> = Box(ComicbookCharacters(universes: [])) | |
func addHero(_ h: Hero) { | |
guard allHeros[h.name] == nil else { return } | |
let heroMO = HeroMO() | |
heroMO.name = h.name | |
allHeros[h.name] = heroMO | |
ordering.append(heroMO.id) | |
} | |
func removeHero(_ h: Hero) { | |
} | |
// our source of truth has changed so we need to update the displayItems | |
private func arrangeHeros() { | |
} | |
private func addHero(_: HeroMO) { | |
} | |
private func add(hero: HeroMO, toOrg: OrganizationMO) { | |
} | |
private func move(_ hero: HeroMO, to index: Int){ | |
} | |
} | |
struct ComicbookCharacters { | |
var universes: [Universe] | |
func displayAll() { | |
universes.forEach({ u in | |
u.displayAll() | |
}) | |
} | |
} | |
struct Universe { | |
var name: String | |
var items: [ListItem] | |
func displayAll() { | |
items.forEach({ item in | |
item.display() | |
}) | |
} | |
} | |
/// represents an interface all items and collection of items have in common | |
protocol Displayable { | |
var displayString: String { get } | |
func display() // this could be any mutation or side affect but lets just print | |
func asType() -> ListItemRepresentable | |
} | |
extension Displayable { | |
func display(){ | |
print(displayString) | |
} | |
} | |
// heres a HeroType that defines its values as well as its Displayable properties in one place | |
struct Hero: Displayable { | |
func display() { | |
print(name) | |
} | |
var name: String | |
var displayString: String { return name } | |
func asType() -> ListItemRepresentable { | |
return .person(self) | |
} | |
} | |
struct Organization { | |
var title: String | |
var members: [Hero] | |
func printAllMembers() { | |
members.map({ print($0) }) | |
} | |
} | |
// Quick Example of how to conform a type, perhaps a 3rd party struct to Displayable in your codebase, many people just prefer extensions over a long definition | |
extension Organization: Displayable { | |
var displayString: String { return title } | |
func asType() -> ListItemRepresentable { | |
return .organization(self) | |
} | |
func display() { | |
print(title) | |
printAllMembers() | |
} | |
} | |
enum ListItemRepresentable { | |
case person(_ : Hero) | |
case organization(_ : Organization) | |
} | |
// Prepare this struct to be displayed in a List in SwiftUI by having an id and conform to Identifiable | |
struct ListItem: Identifiable { | |
// this coold be cached on a per object basis but lets perform based on the type on call for an example of that | |
func display() { | |
switch type { | |
case .person(let person): | |
person.display() | |
case .organization(let organization): | |
organization.display() | |
} | |
} | |
// this could be generated but lets use caching as an example | |
var displayString: String | |
var type: ListItemRepresentable | |
// used to handle identifying this item in a list especially collection differences | |
var id = UUID() | |
init(displayable : Displayable) { | |
self.displayString = displayable.displayString | |
self.type = displayable.asType() | |
} | |
} | |
let spiderMan = Hero(name: "Peter Parker") | |
let captain = Hero(name: "Steve Rogers") | |
let ironMan = Hero(name: "Tony Stark") | |
let thor = Hero(name: "Dr Donald Blake") | |
let avengers = Organization(title: "Avengers", | |
members: [captain,ironMan,thor]) | |
let dareDevil = Hero(name: "Matt Murdock") | |
// we have a homogeneous array that represents a heterogeneous collection | |
var listOfMarvelCharacters = [ | |
ListItem(displayable: spiderMan), | |
ListItem(displayable: avengers), | |
ListItem(displayable: dareDevil), | |
] | |
var marvel = Universe(name: "Marvel", items: listOfMarvelCharacters) | |
let batman = Hero(name: "Bruce Wayne") | |
let superman = Hero(name: "Clark Kent") | |
let wonderWoman = Hero(name: "Diana Prince") | |
let justiceLeage = Organization(title: "Justice Leage", | |
members: [batman,superman,wonderWoman]) | |
let greenArrow = Hero(name: "Oliver Queen") | |
let listOfDCCharacters = [ListItem(displayable: justiceLeage), | |
ListItem(displayable: greenArrow) | |
] | |
let dc = Universe(name: "DC", items: listOfDCCharacters) | |
let comics = ComicbookCharacters(universes: [marvel,dc]) | |
comics.displayAll() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment