mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-04-10 03:13:35 +02:00
WIP: new demo app
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 = ""
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user