WIP: new demo app

This commit is contained in:
John Estropia
2020-08-17 09:06:25 +09:00
parent e720504855
commit d988daa025
62 changed files with 4304 additions and 2 deletions

View File

@@ -0,0 +1,58 @@
//
// Demo
// Copyright © 2020 John Rommel Estropia, Inc. All rights reserved.
import SwiftUI
// MARK: - Modern.TimeZonesDemo
extension Modern.TimeZonesDemo {
// MARK: - Modern.TimeZonesDemo.ItemView
struct ItemView: View {
// MARK: Internal
init(title: String, subtitle: String) {
self.title = title
self.subtitle = subtitle
}
// MARK: View
var body: some View {
VStack(alignment: .leading) {
Text(self.title)
.font(.headline)
.foregroundColor(.primary)
Text(self.subtitle)
.font(.subheadline)
.foregroundColor(.secondary)
}
}
// MARK: FilePrivate
fileprivate let title: String
fileprivate let subtitle: String
}
}
#if DEBUG
struct _Demo_Modern_TimeZone_ItemView_Preview: PreviewProvider {
// MARK: PreviewProvider
static var previews: some View {
Modern.TimeZonesDemo.ItemView(
title: "Item Title",
subtitle: "A subtitle caption for this item"
)
}
}
#endif

View File

@@ -0,0 +1,94 @@
//
// Demo
// Copyright © 2020 John Rommel Estropia, Inc. All rights reserved.
import CoreStore
import SwiftUI
// MARK: - Modern.TimeZonesDemo
extension Modern.TimeZonesDemo {
// MARK: - Modern.TimeZonesDemo.ListView
struct ListView: View {
// MARK: Internal
init(title: String, objects: [Modern.TimeZonesDemo.TimeZone]) {
self.title = title
self.values = objects.map {
(title: $0.name, subtitle: $0.abbreviation)
}
}
init(title: String, value: Any?) {
self.title = title
switch value {
case (let array as [Any])?:
self.values = array.map {
(
title: String(describing: $0),
dsubtitleetail: String(reflecting: type(of: $0))
)
}
case let item?:
self.values = [
(
title: String(describing: item),
subtitle: String(reflecting: type(of: item))
)
]
case nil:
self.values = []
}
}
// MARK: View
var body: some View {
List {
ForEach(self.values, id: \.title) { item in
Modern.TimeZonesDemo.ItemView(
title: item.title,
subtitle: item.subtitle
)
}
}
.navigationBarTitle(self.title)
}
// MARK: Private
private let title: String
private let values: [(title: String, subtitle: String)]
}
}
#if DEBUG
struct _Demo_Modern_TimeZonesDemo_ListView_Preview: PreviewProvider {
// MARK: PreviewProvider
static var previews: some View {
Modern.TimeZonesDemo.ListView(
title: "Title",
objects: try! Modern.TimeZonesDemo.dataStack.fetchAll(
From<Modern.TimeZonesDemo.TimeZone>()
.orderBy(.ascending(\.$name))
)
)
}
}
#endif

View File

@@ -0,0 +1,234 @@
//
// Demo
// Copyright © 2020 John Rommel Estropia, Inc. All rights reserved.
import CoreStore
import SwiftUI
// MARK: - Modern.TimeZonesDemo
extension Modern.TimeZonesDemo {
// MARK: - Modern.TimeZonesDemo.MainView
struct MainView: View {
/**
Sample 1: Plain object fetch
*/
private func fetchAllTimeZones() -> [Modern.TimeZonesDemo.TimeZone] {
return try! Modern.TimeZonesDemo.dataStack.fetchAll(
From<Modern.TimeZonesDemo.TimeZone>()
.orderBy(.ascending(\.$secondsFromGMT))
)
}
/**
Sample 2: Plain object fetch with simple `where` clause
*/
private func fetchTimeZonesWithDST() -> [Modern.TimeZonesDemo.TimeZone] {
return try! Modern.TimeZonesDemo.dataStack.fetchAll(
From<Modern.TimeZonesDemo.TimeZone>()
.where(\.$isDaylightSavingTime == true)
.orderBy(.ascending(\.$name))
)
}
/**
Sample 3: Plain object fetch with custom `where` clause
*/
private func fetchTimeZonesInAsia() -> [Modern.TimeZonesDemo.TimeZone] {
return try! Modern.TimeZonesDemo.dataStack.fetchAll(
From<Modern.TimeZonesDemo.TimeZone>()
.where(
format: "%K BEGINSWITH[c] %@",
String(keyPath: \Modern.TimeZonesDemo.TimeZone.$name),
"Asia"
)
.orderBy(.ascending(\.$secondsFromGMT))
)
}
/**
Sample 4: Plain object fetch with complex `where` clauses
*/
private func fetchTimeZonesNearUTC() -> [Modern.TimeZonesDemo.TimeZone] {
let secondsIn3Hours = 60 * 60 * 3
return try! Modern.TimeZonesDemo.dataStack.fetchAll(
From<Modern.TimeZonesDemo.TimeZone>()
.where((-secondsIn3Hours ... secondsIn3Hours) ~= \.$secondsFromGMT)
/// equivalent to:
/// ```
/// .where(\.$secondsFromGMT >= -secondsIn3Hours
/// && \.$secondsFromGMT <= secondsIn3Hours)
/// ```
.orderBy(.ascending(\.$secondsFromGMT))
)
}
/**
Sample 5: Querying single raw value with simple `select` clause
*/
private func queryNumberOfTimeZones() -> Int? {
return try! Modern.TimeZonesDemo.dataStack.queryValue(
From<Modern.TimeZonesDemo.TimeZone>()
.select(Int.self, .count(\.$name))
)
}
/**
Sample 6: Querying single raw values with `select` and `where` clauses
*/
private func queryTokyoTimeZoneAbbreviation() -> String? {
return try! Modern.TimeZonesDemo.dataStack.queryValue(
From<Modern.TimeZonesDemo.TimeZone>()
.select(String.self, .attribute(\.$abbreviation))
.where(
format: "%K ENDSWITH[c] %@",
String(keyPath: \Modern.TimeZonesDemo.TimeZone.$name),
"Tokyo"
)
)
}
/**
Sample 7: Querying a list of raw values with multiple attributes
*/
private func queryAllNamesAndAbbreviations() -> [[String: Any]]? {
return try! Modern.TimeZonesDemo.dataStack.queryAttributes(
From<Modern.TimeZonesDemo.TimeZone>()
.select(
NSDictionary.self,
.attribute(\.$name),
.attribute(\.$abbreviation)
)
.orderBy(.ascending(\.$name))
)
}
/**
Sample 7: Querying a list of raw values grouped by similar field
*/
private func queryNumberOfCountriesWithAndWithoutDST() -> [[String: Any]]? {
return try! Modern.TimeZonesDemo.dataStack.queryAttributes(
From<Modern.TimeZonesDemo.TimeZone>()
.select(
NSDictionary.self,
.count(\.$isDaylightSavingTime, as: "numberOfCountries"),
.attribute(\.$isDaylightSavingTime)
)
.groupBy(\.$isDaylightSavingTime)
.orderBy(
.ascending(\.$isDaylightSavingTime),
.ascending(\.$name)
)
)
}
// MARK: View
var body: some View {
List {
Section(header: Text("Fetching objects")) {
ForEach(self.fetchingItems, id: \.title) { item in
Menu.ItemView(
title: item.title,
destination: {
Modern.TimeZonesDemo.ListView(
title: item.title,
objects: item.objects()
)
}
)
}
}
Section(header: Text("Querying raw values")) {
ForEach(self.queryingItems, id: \.title) { item in
Menu.ItemView(
title: item.title,
destination: {
Modern.TimeZonesDemo.ListView(
title: item.title,
value: item.value()
)
}
)
}
}
}
.listStyle(GroupedListStyle())
.navigationBarTitle("Time Zones")
}
// MARK: Private
private var fetchingItems: [(title: String, objects: () -> [Modern.TimeZonesDemo.TimeZone])] {
return [
(
"All Time Zones",
self.fetchAllTimeZones
),
(
"Time Zones with Daylight Savings",
self.fetchTimeZonesWithDST
),
(
"Time Zones in Asia",
self.fetchTimeZonesInAsia
),
(
"Time Zones at most 3 hours away from UTC",
self.fetchTimeZonesNearUTC
)
]
}
private var queryingItems: [(title: String, value: () -> Any?)] {
return [
(
"Number of Time Zones",
self.queryNumberOfTimeZones
),
(
"Abbreviation for Tokyo's Time Zone",
self.queryTokyoTimeZoneAbbreviation
),
(
"All Names and Abbreviations",
self.queryAllNamesAndAbbreviations
),
(
"Number of Countries with and without DST",
self.queryNumberOfCountriesWithAndWithoutDST
)
]
}
}
}
#if DEBUG
struct _Demo_Modern_TimeZonesDemo_MainView_Preview: PreviewProvider {
// MARK: PreviewProvider
static var previews: some View {
Modern.TimeZonesDemo.MainView()
}
}
#endif

View File

@@ -0,0 +1,32 @@
//
// Demo
// Copyright © 2020 John Rommel Estropia, Inc. All rights reserved.
import CoreStore
// MARK: - Modern.TimeZonesDemo
extension Modern.TimeZonesDemo {
// MARK: - Modern.TimeZonesDemo.TimeZone
final class TimeZone: CoreStoreObject {
// MARK: Internal
@Field.Stored("secondsFromGMT")
var secondsFromGMT: Int = 0
@Field.Stored("abbreviation")
var abbreviation: String = ""
@Field.Stored("isDaylightSavingTime")
var isDaylightSavingTime: Bool = false
@Field.Stored("daylightSavingTimeOffset")
var daylightSavingTimeOffset: Double = 0
@Field.Stored("name")
var name: String = ""
}
}

View File

@@ -0,0 +1,64 @@
//
// Demo
// Copyright © 2020 John Rommel Estropia, Inc. All rights reserved.
import CoreStore
// MARK: - Modern
extension Modern {
// MARK: - Modern.TimeZonesDemo
/**
Sample usages for creating Fetch and Query clauses for `CoreStoreObject`s
*/
enum TimeZonesDemo {
// MARK: Internal
static let dataStack: DataStack = {
let dataStack = DataStack(
CoreStoreSchema(
modelVersion: "V1",
entities: [
Entity<Modern.TimeZonesDemo.TimeZone>("TimeZone")
],
versionLock: [
"TimeZone": [0x9b1d35108434c8fd, 0x4cb8a80903e66b64, 0x405acca3c1945fe3, 0x3b49dccaee0753d8]
]
)
)
/**
- Important: `addStorageAndWait(_:)` and `perform(synchronous:)` methods were used here to simplify initializing the demo, but in practice the asynchronous function variants are recommended.
*/
try! dataStack.addStorageAndWait(
SQLiteStore(
fileName: "Modern.TimeZonesDemo.sqlite",
localStorageOptions: .recreateStoreOnModelMismatch
)
)
_ = try! dataStack.perform(
synchronous: { (transaction) in
try transaction.deleteAll(From<TimeZone>())
for name in NSTimeZone.knownTimeZoneNames {
let rawTimeZone = NSTimeZone(name: name)!
let cachedTimeZone = transaction.create(Into<TimeZone>())
cachedTimeZone.name = rawTimeZone.name
cachedTimeZone.abbreviation = rawTimeZone.abbreviation ?? ""
cachedTimeZone.secondsFromGMT = rawTimeZone.secondsFromGMT
cachedTimeZone.isDaylightSavingTime = rawTimeZone.isDaylightSavingTime
cachedTimeZone.daylightSavingTimeOffset = rawTimeZone.daylightSavingTimeOffset
}
}
)
return dataStack
}()
}
}