mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-04-24 01:28:37 +02:00
WIP
This commit is contained in:
@@ -7,6 +7,10 @@
|
|||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
B531EFE724EA762D005F247D /* Menu.PlaceholderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B531EFE624EA762D005F247D /* Menu.PlaceholderView.swift */; };
|
||||||
|
B531EFE924EB5A53005F247D /* Modern.PokedexDemo.PokedexEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = B531EFE824EB5A52005F247D /* Modern.PokedexDemo.PokedexEntry.swift */; };
|
||||||
|
B531EFEB24EB5ECD005F247D /* Modern.PokedexDemo.Service.swift in Sources */ = {isa = PBXBuildFile; fileRef = B531EFEA24EB5ECD005F247D /* Modern.PokedexDemo.Service.swift */; };
|
||||||
|
B531EFED24EB7453005F247D /* Modern.PokedexDemo.MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B531EFEC24EB7453005F247D /* Modern.PokedexDemo.MainView.swift */; };
|
||||||
B5A3911D24E5429200E7E8BD /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A3911C24E5429200E7E8BD /* AppDelegate.swift */; };
|
B5A3911D24E5429200E7E8BD /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A3911C24E5429200E7E8BD /* AppDelegate.swift */; };
|
||||||
B5A3911F24E5429200E7E8BD /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A3911E24E5429200E7E8BD /* SceneDelegate.swift */; };
|
B5A3911F24E5429200E7E8BD /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A3911E24E5429200E7E8BD /* SceneDelegate.swift */; };
|
||||||
B5A3912124E5429200E7E8BD /* Menu.MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A3912024E5429200E7E8BD /* Menu.MainView.swift */; };
|
B5A3912124E5429200E7E8BD /* Menu.MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A3912024E5429200E7E8BD /* Menu.MainView.swift */; };
|
||||||
@@ -81,6 +85,10 @@
|
|||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
B531EFE624EA762D005F247D /* Menu.PlaceholderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Menu.PlaceholderView.swift; sourceTree = "<group>"; };
|
||||||
|
B531EFE824EB5A52005F247D /* Modern.PokedexDemo.PokedexEntry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.PokedexEntry.swift; sourceTree = "<group>"; };
|
||||||
|
B531EFEA24EB5ECD005F247D /* Modern.PokedexDemo.Service.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.Service.swift; sourceTree = "<group>"; };
|
||||||
|
B531EFEC24EB7453005F247D /* Modern.PokedexDemo.MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.MainView.swift; sourceTree = "<group>"; };
|
||||||
B5A3911924E5429200E7E8BD /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
B5A3911924E5429200E7E8BD /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
B5A3911C24E5429200E7E8BD /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
B5A3911C24E5429200E7E8BD /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
B5A3911E24E5429200E7E8BD /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
B5A3911E24E5429200E7E8BD /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||||
@@ -217,6 +225,7 @@
|
|||||||
B5A3913324E6170500E7E8BD /* Menu.swift */,
|
B5A3913324E6170500E7E8BD /* Menu.swift */,
|
||||||
B5A3912024E5429200E7E8BD /* Menu.MainView.swift */,
|
B5A3912024E5429200E7E8BD /* Menu.MainView.swift */,
|
||||||
B5A3915224E6537F00E7E8BD /* Menu.ItemView.swift */,
|
B5A3915224E6537F00E7E8BD /* Menu.ItemView.swift */,
|
||||||
|
B531EFE624EA762D005F247D /* Menu.PlaceholderView.swift */,
|
||||||
);
|
);
|
||||||
path = Menu;
|
path = Menu;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -364,6 +373,8 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
B5A391B024E96AF600E7E8BD /* Modern.PokedexDemo.swift */,
|
B5A391B024E96AF600E7E8BD /* Modern.PokedexDemo.swift */,
|
||||||
|
B531EFEA24EB5ECD005F247D /* Modern.PokedexDemo.Service.swift */,
|
||||||
|
B531EFEC24EB7453005F247D /* Modern.PokedexDemo.MainView.swift */,
|
||||||
B5A391B224E96B7400E7E8BD /* Models */,
|
B5A391B224E96B7400E7E8BD /* Models */,
|
||||||
);
|
);
|
||||||
path = PokedexDemo;
|
path = PokedexDemo;
|
||||||
@@ -372,6 +383,7 @@
|
|||||||
B5A391B224E96B7400E7E8BD /* Models */ = {
|
B5A391B224E96B7400E7E8BD /* Models */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
B531EFE824EB5A52005F247D /* Modern.PokedexDemo.PokedexEntry.swift */,
|
||||||
B5A391B324E96C0A00E7E8BD /* Modern.PokedexDemo.PokemonSpecies.swift */,
|
B5A391B324E96C0A00E7E8BD /* Modern.PokedexDemo.PokemonSpecies.swift */,
|
||||||
B5A391B824E96F8500E7E8BD /* Modern.PokedexDemo.PokemonForm.swift */,
|
B5A391B824E96F8500E7E8BD /* Modern.PokedexDemo.PokemonForm.swift */,
|
||||||
B5A391B524E96C5500E7E8BD /* Modern.PokedexDemo.Move.swift */,
|
B5A391B524E96C5500E7E8BD /* Modern.PokedexDemo.Move.swift */,
|
||||||
@@ -460,46 +472,50 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
B5A3918824E7A8F900E7E8BD /* Modern.TimeZonesDemo.MainView.swift in Sources */,
|
B5A391A824E90F1000E7E8BD /* UIImage+Extensions.swift in Sources */,
|
||||||
B5A391AE24E9150F00E7E8BD /* Modern.ColorsDemo.UIKit.DetailViewController.swift in Sources */,
|
|
||||||
B5A391A224E8F01F00E7E8BD /* Modern.ColorsDemo.UIKit.ListViewController.swift in Sources */,
|
|
||||||
B5A391AA24E9104300E7E8BD /* Modern.ColorsDemo.UIKit.ItemCell.swift in Sources */,
|
|
||||||
B5A3917C24E6A76C00E7E8BD /* LazyView.swift in Sources */,
|
|
||||||
B5A3918324E7A21800E7E8BD /* Modern.TimeZonesDemo.swift in Sources */,
|
|
||||||
B5A3915324E6537F00E7E8BD /* Menu.ItemView.swift in Sources */,
|
|
||||||
B5A3911D24E5429200E7E8BD /* AppDelegate.swift in Sources */,
|
B5A3911D24E5429200E7E8BD /* AppDelegate.swift in Sources */,
|
||||||
B5A391A024E8F00A00E7E8BD /* Modern.ColorsDemo.UIKit.swift in Sources */,
|
|
||||||
B5A3913424E6170500E7E8BD /* Menu.swift in Sources */,
|
|
||||||
B5A391B924E96F8500E7E8BD /* Modern.PokedexDemo.PokemonForm.swift in Sources */,
|
|
||||||
B5A3918624E7A54A00E7E8BD /* Modern.TimeZonesDemo.TimeZone.swift in Sources */,
|
|
||||||
B5A3915B24E685FE00E7E8BD /* Modern.swift in Sources */,
|
|
||||||
B5A391BB24E970A400E7E8BD /* Modern.PokedexDemo.PokemonType.swift in Sources */,
|
|
||||||
B5A3919624E7E4AC00E7E8BD /* Modern.ColorsDemo.SwiftUI.ItemView.swift in Sources */,
|
|
||||||
B5A3919A24E8207A00E7E8BD /* Modern.ColorsDemo.SwiftUI.DetailView.swift in Sources */,
|
|
||||||
B5A3916024E6925900E7E8BD /* Modern.PlacemarksDemo.MapView.swift in Sources */,
|
|
||||||
B5A391B124E96AF600E7E8BD /* Modern.PokedexDemo.swift in Sources */,
|
|
||||||
B5A3918A24E7AD1800E7E8BD /* Modern.TimeZonesDemo.ListView.swift in Sources */,
|
|
||||||
B5A3911F24E5429200E7E8BD /* SceneDelegate.swift in Sources */,
|
|
||||||
B5A3915924E685EC00E7E8BD /* Classic.swift in Sources */,
|
B5A3915924E685EC00E7E8BD /* Classic.swift in Sources */,
|
||||||
B5A3919824E7E67000E7E8BD /* Modern.ColorsDemo.Filter.swift in Sources */,
|
B5A3918024E787D900E7E8BD /* InstructionsView.swift in Sources */,
|
||||||
B5A391B624E96C5500E7E8BD /* Modern.PokedexDemo.Move.swift in Sources */,
|
B5A3917C24E6A76C00E7E8BD /* LazyView.swift in Sources */,
|
||||||
B5A3916224E697BA00E7E8BD /* Modern.PlacemarksDemo.MainView.swift in Sources */,
|
B5A3913424E6170500E7E8BD /* Menu.swift in Sources */,
|
||||||
B5A3917E24E7728400E7E8BD /* Modern.PlacemarksDemo.Geocoder.swift in Sources */,
|
B5A3915B24E685FE00E7E8BD /* Modern.swift in Sources */,
|
||||||
B5A391A424E8F04300E7E8BD /* Modern.ColorsDemo.UIKit.ListView.swift in Sources */,
|
B5A3911F24E5429200E7E8BD /* SceneDelegate.swift in Sources */,
|
||||||
B5A391AC24E9143B00E7E8BD /* Modern.ColorsDemo.UIKit.DetailView.swift in Sources */,
|
B5A3915324E6537F00E7E8BD /* Menu.ItemView.swift in Sources */,
|
||||||
B5A3919224E7E0C600E7E8BD /* Modern.ColorsDemo.Palette.swift in Sources */,
|
B5A3912124E5429200E7E8BD /* Menu.MainView.swift in Sources */,
|
||||||
B5A3919424E7E36700E7E8BD /* Modern.ColorsDemo.SwiftUI.ListView.swift in Sources */,
|
B531EFE724EA762D005F247D /* Menu.PlaceholderView.swift in Sources */,
|
||||||
B5A3918F24E7E06500E7E8BD /* Modern.ColorsDemo.swift in Sources */,
|
B5A3918F24E7E06500E7E8BD /* Modern.ColorsDemo.swift in Sources */,
|
||||||
B5A3915E24E6922E00E7E8BD /* Modern.PlacemarksDemo.swift in Sources */,
|
B5A3915E24E6922E00E7E8BD /* Modern.PlacemarksDemo.swift in Sources */,
|
||||||
B5A391B424E96C0A00E7E8BD /* Modern.PokedexDemo.PokemonSpecies.swift in Sources */,
|
B5A391B124E96AF600E7E8BD /* Modern.PokedexDemo.swift in Sources */,
|
||||||
B5A391A824E90F1000E7E8BD /* UIImage+Extensions.swift in Sources */,
|
B5A3918324E7A21800E7E8BD /* Modern.TimeZonesDemo.swift in Sources */,
|
||||||
B5A3918024E787D900E7E8BD /* InstructionsView.swift in Sources */,
|
B531EFEB24EB5ECD005F247D /* Modern.PokedexDemo.Service.swift in Sources */,
|
||||||
B5A3918C24E7B44B00E7E8BD /* Modern.TimeZonesDemo.ItemView.swift in Sources */,
|
B5A3919824E7E67000E7E8BD /* Modern.ColorsDemo.Filter.swift in Sources */,
|
||||||
B5A3919E24E8EEB600E7E8BD /* Modern.ColorsDemo.SwiftUI.swift in Sources */,
|
|
||||||
B5A391A624E8F4EA00E7E8BD /* Modern.ColorsDemo.MainView.swift in Sources */,
|
B5A391A624E8F4EA00E7E8BD /* Modern.ColorsDemo.MainView.swift in Sources */,
|
||||||
|
B5A3919224E7E0C600E7E8BD /* Modern.ColorsDemo.Palette.swift in Sources */,
|
||||||
|
B5A3919E24E8EEB600E7E8BD /* Modern.ColorsDemo.SwiftUI.swift in Sources */,
|
||||||
|
B5A391A024E8F00A00E7E8BD /* Modern.ColorsDemo.UIKit.swift in Sources */,
|
||||||
|
B5A3917E24E7728400E7E8BD /* Modern.PlacemarksDemo.Geocoder.swift in Sources */,
|
||||||
|
B5A3916224E697BA00E7E8BD /* Modern.PlacemarksDemo.MainView.swift in Sources */,
|
||||||
|
B5A3916024E6925900E7E8BD /* Modern.PlacemarksDemo.MapView.swift in Sources */,
|
||||||
B5A3916524E698C700E7E8BD /* Modern.PlacemarksDemo.Place.swift in Sources */,
|
B5A3916524E698C700E7E8BD /* Modern.PlacemarksDemo.Place.swift in Sources */,
|
||||||
B5A391BD24E977E500E7E8BD /* Modern.PokedexDemo.Ability.swift in Sources */,
|
B5A391BD24E977E500E7E8BD /* Modern.PokedexDemo.Ability.swift in Sources */,
|
||||||
B5A3912124E5429200E7E8BD /* Menu.MainView.swift in Sources */,
|
B5A391B624E96C5500E7E8BD /* Modern.PokedexDemo.Move.swift in Sources */,
|
||||||
|
B531EFE924EB5A53005F247D /* Modern.PokedexDemo.PokedexEntry.swift in Sources */,
|
||||||
|
B5A391B924E96F8500E7E8BD /* Modern.PokedexDemo.PokemonForm.swift in Sources */,
|
||||||
|
B5A391B424E96C0A00E7E8BD /* Modern.PokedexDemo.PokemonSpecies.swift in Sources */,
|
||||||
|
B5A391BB24E970A400E7E8BD /* Modern.PokedexDemo.PokemonType.swift in Sources */,
|
||||||
|
B5A3918C24E7B44B00E7E8BD /* Modern.TimeZonesDemo.ItemView.swift in Sources */,
|
||||||
|
B5A3918A24E7AD1800E7E8BD /* Modern.TimeZonesDemo.ListView.swift in Sources */,
|
||||||
|
B5A3918824E7A8F900E7E8BD /* Modern.TimeZonesDemo.MainView.swift in Sources */,
|
||||||
|
B531EFED24EB7453005F247D /* Modern.PokedexDemo.MainView.swift in Sources */,
|
||||||
|
B5A3918624E7A54A00E7E8BD /* Modern.TimeZonesDemo.TimeZone.swift in Sources */,
|
||||||
|
B5A3919A24E8207A00E7E8BD /* Modern.ColorsDemo.SwiftUI.DetailView.swift in Sources */,
|
||||||
|
B5A3919624E7E4AC00E7E8BD /* Modern.ColorsDemo.SwiftUI.ItemView.swift in Sources */,
|
||||||
|
B5A3919424E7E36700E7E8BD /* Modern.ColorsDemo.SwiftUI.ListView.swift in Sources */,
|
||||||
|
B5A391AC24E9143B00E7E8BD /* Modern.ColorsDemo.UIKit.DetailView.swift in Sources */,
|
||||||
|
B5A391AE24E9150F00E7E8BD /* Modern.ColorsDemo.UIKit.DetailViewController.swift in Sources */,
|
||||||
|
B5A391AA24E9104300E7E8BD /* Modern.ColorsDemo.UIKit.ItemCell.swift in Sources */,
|
||||||
|
B5A391A424E8F04300E7E8BD /* Modern.ColorsDemo.UIKit.ListView.swift in Sources */,
|
||||||
|
B5A391A224E8F01F00E7E8BD /* Modern.ColorsDemo.UIKit.ListViewController.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -533,7 +549,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = appIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
@@ -607,7 +623,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = appIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
|
||||||
<capability name="Named colors" minToolsVersion="9.0"/>
|
|
||||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
@@ -19,20 +18,24 @@
|
|||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright © 2020 John Rommel Estropia. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="Yn3-8H-uzI">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright © 2020 John Rommel Estropia. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="Yn3-8H-uzI">
|
||||||
<rect key="frame" x="20" y="827" width="374" height="21"/>
|
<rect key="frame" x="20" y="827" width="374" height="21"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<color key="textColor" name="foreground"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<imageView userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="coreStoreIcon" translatesAutoresizingMaskIntoConstraints="NO" id="IrK-8p-pit">
|
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="CoreStoreIcon" translatesAutoresizingMaskIntoConstraints="NO" id="IrK-8p-pit">
|
||||||
<rect key="frame" x="37" y="143.5" width="340" height="340"/>
|
<rect key="frame" x="122" y="228.5" width="170" height="170"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" secondItem="IrK-8p-pit" secondAttribute="height" multiplier="1:1" id="WaM-8F-33r"/>
|
||||||
|
<constraint firstAttribute="width" constant="170" id="dlo-1N-ikz"/>
|
||||||
|
</constraints>
|
||||||
</imageView>
|
</imageView>
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="CoreStore" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="8Vu-0U-3hd">
|
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="CoreStore" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="8Vu-0U-3hd">
|
||||||
<rect key="frame" x="20" y="503.5" width="374" height="57.5"/>
|
<rect key="frame" x="20" y="418.5" width="374" height="57.5"/>
|
||||||
<fontDescription key="fontDescription" name="HelveticaNeue-UltraLight" family="Helvetica Neue" pointSize="50"/>
|
<fontDescription key="fontDescription" name="HelveticaNeue-UltraLight" family="Helvetica Neue" pointSize="50"/>
|
||||||
<color key="textColor" name="foreground"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" name="background"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="Yn3-8H-uzI" firstAttribute="leading" secondItem="Bp2-lt-3DL" secondAttribute="leading" constant="20" symbolic="YES" id="7Dq-xP-k2v"/>
|
<constraint firstItem="Yn3-8H-uzI" firstAttribute="leading" secondItem="Bp2-lt-3DL" secondAttribute="leading" constant="20" symbolic="YES" id="7Dq-xP-k2v"/>
|
||||||
<constraint firstItem="IrK-8p-pit" firstAttribute="centerY" secondItem="Bp2-lt-3DL" secondAttribute="centerY" multiplier="0.7" id="HUz-XL-l27"/>
|
<constraint firstItem="IrK-8p-pit" firstAttribute="centerY" secondItem="Bp2-lt-3DL" secondAttribute="centerY" multiplier="0.7" id="HUz-XL-l27"/>
|
||||||
@@ -52,12 +55,6 @@
|
|||||||
</scene>
|
</scene>
|
||||||
</scenes>
|
</scenes>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="coreStoreIcon" width="340" height="340"/>
|
<image name="CoreStoreIcon" width="170" height="170"/>
|
||||||
<namedColor name="background">
|
|
||||||
<color red="0.15700000524520874" green="0.2199999988079071" blue="0.29399999976158142" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
|
||||||
</namedColor>
|
|
||||||
<namedColor name="foreground">
|
|
||||||
<color red="0.90600001811981201" green="0.92500001192092896" blue="0.92900002002716064" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
|
||||||
</namedColor>
|
|
||||||
</resources>
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ extension Modern.ColorsDemo {
|
|||||||
|
|
||||||
private static func randomSaturation() -> Float {
|
private static func randomSaturation() -> Float {
|
||||||
|
|
||||||
return Float.random(in: 0.0 ... 1.0)
|
return Float.random(in: 0.4 ... 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func randomBrightness() -> Float {
|
private static func randomBrightness() -> Float {
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
//
|
||||||
|
// Demo
|
||||||
|
// Copyright © 2020 John Rommel Estropia, Inc. All rights reserved.
|
||||||
|
|
||||||
|
import Combine
|
||||||
|
import CoreStore
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
// MARK: - Modern.PokedexDemo
|
||||||
|
|
||||||
|
extension Modern.PokedexDemo {
|
||||||
|
|
||||||
|
// MARK: - Modern.PokedexDemo.MainView
|
||||||
|
|
||||||
|
struct MainView: View {
|
||||||
|
|
||||||
|
/**
|
||||||
|
⭐️ Sample 1: Setting a sectioned `ListPublisher` declared as an `@ObservedObject`
|
||||||
|
*/
|
||||||
|
@ObservedObject
|
||||||
|
private var pokedexEntries: ListPublisher<Modern.PokedexDemo.PokedexEntry>
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Internal
|
||||||
|
|
||||||
|
init() {
|
||||||
|
|
||||||
|
self.pokedexEntries = Modern.PokedexDemo.pokedexEntries
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: View
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
List() {
|
||||||
|
ForEach(self.pokedexEntries.snapshot, id: \.self) { pokedexEntry in
|
||||||
|
LazyView {
|
||||||
|
Text(pokedexEntry.snapshot?.$id ?? "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.overlay(
|
||||||
|
InstructionsView(
|
||||||
|
("Random", "Sets random coordinate"),
|
||||||
|
("Tap", "Sets to tapped coordinate")
|
||||||
|
)
|
||||||
|
.padding(.leading, 10)
|
||||||
|
.padding(.bottom, 40),
|
||||||
|
alignment: .bottomLeading
|
||||||
|
)
|
||||||
|
.navigationBarTitle("Pokedex")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Private
|
||||||
|
|
||||||
|
private let service: Modern.PokedexDemo.Service = .init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
|
||||||
|
struct _Demo_Modern_PokedexDemo_MainView_Preview: PreviewProvider {
|
||||||
|
|
||||||
|
// MARK: PreviewProvider
|
||||||
|
|
||||||
|
static var previews: some View {
|
||||||
|
|
||||||
|
Modern.PokedexDemo.MainView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// Demo
|
||||||
|
// Copyright © 2020 John Rommel Estropia, Inc. All rights reserved.
|
||||||
|
|
||||||
|
import CoreStore
|
||||||
|
|
||||||
|
// MARK: - Modern.PokedexDemo
|
||||||
|
|
||||||
|
extension Modern.PokedexDemo {
|
||||||
|
|
||||||
|
// MARK: - Modern.PokedexDemo.PokedexEntry
|
||||||
|
|
||||||
|
final class PokedexEntry: CoreStoreObject, ImportableUniqueObject {
|
||||||
|
|
||||||
|
// MARK: Internal
|
||||||
|
|
||||||
|
@Field.Stored("id")
|
||||||
|
var id: String = ""
|
||||||
|
|
||||||
|
@Field.Stored("url")
|
||||||
|
var url: URL!
|
||||||
|
|
||||||
|
|
||||||
|
@Field.Relationship("form")
|
||||||
|
var form: Modern.PokedexDemo.PokemonForm?
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: ImportableObject
|
||||||
|
|
||||||
|
typealias ImportSource = Dictionary<String, Any>
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: ImportableUniqueObject
|
||||||
|
|
||||||
|
static let uniqueIDKeyPath: String = String(keyPath: \Modern.PokedexDemo.PokedexEntry.$id)
|
||||||
|
|
||||||
|
var uniqueIDValue: String {
|
||||||
|
|
||||||
|
get {
|
||||||
|
|
||||||
|
return self.id
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
|
||||||
|
self.id = newValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func uniqueID(from source: ImportSource, in transaction: BaseDataTransaction) throws -> String? {
|
||||||
|
|
||||||
|
return try Modern.PokedexDemo.Service.parseJSON(source["name"])
|
||||||
|
}
|
||||||
|
|
||||||
|
func update(from source: ImportSource, in transaction: BaseDataTransaction) throws {
|
||||||
|
|
||||||
|
self.url = URL(string: try Modern.PokedexDemo.Service.parseJSON(source["url"]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,15 +19,18 @@ extension Modern.PokedexDemo {
|
|||||||
|
|
||||||
@Field.Stored("name")
|
@Field.Stored("name")
|
||||||
var name: String = ""
|
var name: String = ""
|
||||||
|
|
||||||
|
@Field.Stored("weight")
|
||||||
|
var weight: Int = 0
|
||||||
|
|
||||||
@Field.Stored("pokemonType1")
|
@Field.Stored("pokemonType1")
|
||||||
var pokemonType1: Modern.PokedexDemo.PokemonType = .normal
|
var pokemonType1: Modern.PokedexDemo.PokemonType = .normal
|
||||||
|
|
||||||
@Field.Stored("pokemonType2")
|
@Field.Stored("pokemonType2")
|
||||||
var pokemonType2: Modern.PokedexDemo.PokemonType?
|
var pokemonType2: Modern.PokedexDemo.PokemonType?
|
||||||
|
|
||||||
@Field.Relationship("species")
|
@Field.Stored("spriteURL")
|
||||||
var species: Modern.PokedexDemo.PokemonSpecies?
|
var spriteURL: URL?
|
||||||
|
|
||||||
|
|
||||||
@Field.Stored("statHitPoints")
|
@Field.Stored("statHitPoints")
|
||||||
@@ -49,23 +52,17 @@ extension Modern.PokedexDemo {
|
|||||||
var statSpeed: Int = 0
|
var statSpeed: Int = 0
|
||||||
|
|
||||||
|
|
||||||
@Field.Stored("spriteFrontURL")
|
|
||||||
var spriteFrontURL: URL?
|
|
||||||
|
|
||||||
@Field.Stored("spriteBackURL")
|
|
||||||
var spriteBackURL: URL?
|
|
||||||
|
|
||||||
@Field.Stored("spriteShinyFrontURL")
|
|
||||||
var spriteShinyFrontURL: URL?
|
|
||||||
|
|
||||||
@Field.Stored("spriteShinyBackURL")
|
|
||||||
var spriteShinyBackURL: URL?
|
|
||||||
|
|
||||||
|
|
||||||
@Field.Relationship("abilities", inverse: \.$learners)
|
@Field.Relationship("abilities", inverse: \.$learners)
|
||||||
var abilities: Set<Modern.PokedexDemo.Ability>
|
var abilities: Set<Modern.PokedexDemo.Ability>
|
||||||
|
|
||||||
@Field.Relationship("moves", inverse: \.$learners)
|
@Field.Relationship("moves", inverse: \.$learners)
|
||||||
var moves: Set<Modern.PokedexDemo.Move>
|
var moves: Set<Modern.PokedexDemo.Move>
|
||||||
|
|
||||||
|
|
||||||
|
@Field.Relationship("pokedexEntry", inverse: \.$form)
|
||||||
|
var pokedexEntry: Modern.PokedexDemo.PokedexEntry?
|
||||||
|
|
||||||
|
@Field.Relationship("species", inverse: \.$forms)
|
||||||
|
var species: Modern.PokedexDemo.PokemonSpecies?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,9 @@ extension Modern.PokedexDemo {
|
|||||||
|
|
||||||
@Field.Stored("weight")
|
@Field.Stored("weight")
|
||||||
var weight: Int = 0
|
var weight: Int = 0
|
||||||
|
|
||||||
|
|
||||||
@Field.Relationship("forms", inverse: \.$species)
|
@Field.Relationship("forms")
|
||||||
var forms: Set<Modern.PokedexDemo.PokemonForm>
|
var forms: Set<Modern.PokedexDemo.PokemonForm>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,169 @@
|
|||||||
|
//
|
||||||
|
// Demo
|
||||||
|
// Copyright © 2020 John Rommel Estropia, Inc. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Combine
|
||||||
|
import CoreStore
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - Modern.PokedexDemo
|
||||||
|
|
||||||
|
extension Modern.PokedexDemo {
|
||||||
|
|
||||||
|
// MARK: - Modern.PokedexDemo.Service
|
||||||
|
|
||||||
|
final class Service {
|
||||||
|
|
||||||
|
// MARK: Internal
|
||||||
|
|
||||||
|
@Published
|
||||||
|
var isLoading: Bool = true
|
||||||
|
|
||||||
|
@Published
|
||||||
|
var lastError: (error: Modern.PokedexDemo.Service.Error, retry: () -> Void)?
|
||||||
|
|
||||||
|
init() {
|
||||||
|
|
||||||
|
self.fetchPokedexEntries()
|
||||||
|
}
|
||||||
|
|
||||||
|
static func parseJSON<Output>(_ json: Any?) throws -> Output {
|
||||||
|
|
||||||
|
switch json {
|
||||||
|
|
||||||
|
case let json as Output:
|
||||||
|
return json
|
||||||
|
|
||||||
|
case let any:
|
||||||
|
throw Modern.PokedexDemo.Service.Error.parseError(
|
||||||
|
expected: Output.self,
|
||||||
|
actual: type(of: any)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchPokedexEntries() {
|
||||||
|
|
||||||
|
self.cancellable["pokedexEntries"] = self.pokedexEntries
|
||||||
|
.handleEvents(
|
||||||
|
receiveSubscription: { [weak self] _ in
|
||||||
|
|
||||||
|
print("Fetching Pokedex Entries")
|
||||||
|
guard let self = self else {
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.lastError = nil
|
||||||
|
self.isLoading = true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.sink(
|
||||||
|
receiveCompletion: { [weak self] completion in
|
||||||
|
|
||||||
|
print("Result (Fetching Pokedex Entries): \(completion)")
|
||||||
|
guard let self = self else {
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.isLoading = false
|
||||||
|
switch completion {
|
||||||
|
|
||||||
|
case .finished:
|
||||||
|
self.lastError = nil
|
||||||
|
|
||||||
|
case .failure(let error):
|
||||||
|
self.lastError = (
|
||||||
|
error: error,
|
||||||
|
retry: { [weak self] in
|
||||||
|
|
||||||
|
self?.fetchPokedexEntries()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
receiveValue: {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchPokemonForm(for pokedexEntry: ObjectSnapshot<Modern.PokedexDemo.PokedexEntry>) {
|
||||||
|
|
||||||
|
self.cancellable["pokedexEntry.\(pokedexEntry.$id)"] = URLSession.shared
|
||||||
|
.dataTaskPublisher(for: pokedexEntry.$url!)
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.eraseToAnyPublisher()
|
||||||
|
.sink(
|
||||||
|
receiveCompletion: { _ in },
|
||||||
|
receiveValue: { _ in
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: Private
|
||||||
|
|
||||||
|
private var cancellable: Dictionary<String, AnyCancellable> = [:]
|
||||||
|
|
||||||
|
private lazy var pokedexEntries: AnyPublisher<Void, Modern.PokedexDemo.Service.Error> = URLSession.shared
|
||||||
|
.dataTaskPublisher(
|
||||||
|
for: URL(string: "https://pokeapi.co/api/v2/pokemon?limit=10000&offset=0")!
|
||||||
|
)
|
||||||
|
.mapError({ .networkError($0) })
|
||||||
|
.flatMap(
|
||||||
|
{ output in
|
||||||
|
|
||||||
|
return Future<Void, Modern.PokedexDemo.Service.Error> { promise in
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
|
let json: Dictionary<String, Any> = try Self.parseJSON(
|
||||||
|
try JSONSerialization.jsonObject(with: output.data, options: [])
|
||||||
|
)
|
||||||
|
let results: [Dictionary<String, Any>] = try Self.parseJSON(
|
||||||
|
json["results"]
|
||||||
|
)
|
||||||
|
Modern.PokedexDemo.dataStack.perform(
|
||||||
|
asynchronous: { transaction -> Void in
|
||||||
|
|
||||||
|
_ = try transaction.importUniqueObjects(
|
||||||
|
Into<Modern.PokedexDemo.PokedexEntry>(),
|
||||||
|
sourceArray: results
|
||||||
|
)
|
||||||
|
},
|
||||||
|
success: { result in
|
||||||
|
|
||||||
|
promise(.success(result))
|
||||||
|
},
|
||||||
|
failure: { error in
|
||||||
|
|
||||||
|
promise(.failure(.saveError(error)))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
catch let error as Modern.PokedexDemo.Service.Error {
|
||||||
|
|
||||||
|
promise(.failure(error))
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
|
||||||
|
promise(.failure(.otherError(error)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.eraseToAnyPublisher()
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - Modern.PokedexDemo.Service.Error
|
||||||
|
|
||||||
|
enum Error: Swift.Error {
|
||||||
|
|
||||||
|
case networkError(URLError)
|
||||||
|
case parseError(expected: Any.Type, actual: Any.Type)
|
||||||
|
case saveError(CoreStoreError)
|
||||||
|
case otherError(Swift.Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,10 +23,11 @@ extension Modern {
|
|||||||
CoreStoreSchema(
|
CoreStoreSchema(
|
||||||
modelVersion: "V1",
|
modelVersion: "V1",
|
||||||
entities: [
|
entities: [
|
||||||
Entity<Modern.ColorsDemo.Palette>("Palette")
|
Entity<Modern.PokedexDemo.PokedexEntry>("PokedexEntry"),
|
||||||
],
|
Entity<Modern.PokedexDemo.PokemonSpecies>("PokemonSpecies"),
|
||||||
versionLock: [
|
Entity<Modern.PokedexDemo.PokemonForm>("PokemonForm"),
|
||||||
"Palette": [0xbaf4eaee9353176a, 0xdd6ca918cc2b0c38, 0xd04fad8882d7cc34, 0x3e90ca38c091503f]
|
Entity<Modern.PokedexDemo.Move>("Move"),
|
||||||
|
Entity<Modern.PokedexDemo.Ability>("Ability")
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -36,31 +37,16 @@ extension Modern {
|
|||||||
*/
|
*/
|
||||||
try! dataStack.addStorageAndWait(
|
try! dataStack.addStorageAndWait(
|
||||||
SQLiteStore(
|
SQLiteStore(
|
||||||
fileName: "Modern.ColorsDemo.sqlite",
|
fileName: "Modern.PokedexDemo.sqlite",
|
||||||
localStorageOptions: .recreateStoreOnModelMismatch
|
localStorageOptions: .recreateStoreOnModelMismatch
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return dataStack
|
return dataStack
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static let palettesPublisher: ListPublisher<Modern.ColorsDemo.Palette> = Modern.ColorsDemo.dataStack.publishList(
|
static let pokedexEntries: ListPublisher<Modern.PokedexDemo.PokedexEntry> = Modern.PokedexDemo.dataStack.publishList(
|
||||||
From<Modern.ColorsDemo.Palette>()
|
From<Modern.PokedexDemo.PokedexEntry>()
|
||||||
.sectionBy(\.$colorName)
|
.orderBy(.ascending(\.$id))
|
||||||
.where(Modern.ColorsDemo.filter.whereClause())
|
|
||||||
.orderBy(.ascending(\.$hue))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
static var filter: Modern.ColorsDemo.Filter = .all {
|
|
||||||
|
|
||||||
didSet {
|
|
||||||
|
|
||||||
try! Modern.ColorsDemo.palettesPublisher.refetch(
|
|
||||||
From<Modern.ColorsDemo.Palette>()
|
|
||||||
.sectionBy(\.$colorName)
|
|
||||||
.where(self.filter.whereClause())
|
|
||||||
.orderBy(.ascending(\.$hue))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,9 @@ extension Menu {
|
|||||||
Menu.ItemView(
|
Menu.ItemView(
|
||||||
title: "Pokedex API",
|
title: "Pokedex API",
|
||||||
subtitle: "Importing JSON data from external source",
|
subtitle: "Importing JSON data from external source",
|
||||||
destination: { EmptyView() }
|
destination: {
|
||||||
|
Modern.PokedexDemo.MainView()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Section(header: Text("Classic (NSManagedObject subclasses)")) {
|
Section(header: Text("Classic (NSManagedObject subclasses)")) {
|
||||||
@@ -127,23 +129,11 @@ extension Menu {
|
|||||||
}
|
}
|
||||||
.listStyle(GroupedListStyle())
|
.listStyle(GroupedListStyle())
|
||||||
.navigationBarTitle("CoreStore Demos")
|
.navigationBarTitle("CoreStore Demos")
|
||||||
Menu.DetailView()
|
Menu.PlaceholderView()
|
||||||
}
|
}
|
||||||
.navigationViewStyle(DoubleColumnNavigationViewStyle())
|
.navigationViewStyle(DoubleColumnNavigationViewStyle())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate struct DetailView: View {
|
|
||||||
|
|
||||||
var selectedDate: Date?
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
Group {
|
|
||||||
Text("Detail view content goes here")
|
|
||||||
}
|
|
||||||
.navigationBarTitle(Text("Detail"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
|||||||
44
Demo/Sources/Helpers/Menu/Menu.PlaceholderView.swift
Normal file
44
Demo/Sources/Helpers/Menu/Menu.PlaceholderView.swift
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
//
|
||||||
|
// Demo
|
||||||
|
// Copyright © 2020 John Rommel Estropia, Inc. All rights reserved.
|
||||||
|
|
||||||
|
import Combine
|
||||||
|
import CoreStore
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
// MARK: - Menu
|
||||||
|
|
||||||
|
extension Menu {
|
||||||
|
|
||||||
|
// MARK: - Menu.PlaceholderView
|
||||||
|
|
||||||
|
struct PlaceholderView: UIViewControllerRepresentable {
|
||||||
|
|
||||||
|
// MARK: UIViewControllerRepresentable
|
||||||
|
|
||||||
|
typealias UIViewControllerType = UIViewController
|
||||||
|
|
||||||
|
func makeUIViewController(context: Self.Context) -> UIViewControllerType {
|
||||||
|
|
||||||
|
return UIStoryboard(name: "LaunchScreen", bundle: nil).instantiateInitialViewController()!
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Self.Context) {}
|
||||||
|
|
||||||
|
static func dismantleUIViewController(_ uiViewController: UIViewControllerType, coordinator: Void) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
|
||||||
|
struct _Demo_Menu_PlaceholderView_Preview: PreviewProvider {
|
||||||
|
|
||||||
|
// MARK: PreviewProvider
|
||||||
|
|
||||||
|
static var previews: some View {
|
||||||
|
|
||||||
|
return Menu.PlaceholderView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -368,6 +368,18 @@ extension From where O: CoreStoreObject {
|
|||||||
|
|
||||||
return self.sectionBy(O.meta[keyPath: sectionKeyPath].keyPath, { $0 })
|
return self.sectionBy(O.meta[keyPath: sectionKeyPath].keyPath, { $0 })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates a `SectionMonitorChainBuilder` with the key path to use to group `ListMonitor` objects into sections
|
||||||
|
|
||||||
|
- parameter sectionKeyPath: the `KeyPath` to use to group the objects into sections
|
||||||
|
- returns: a `SectionMonitorChainBuilder` that is sectioned by the specified key path
|
||||||
|
*/
|
||||||
|
@available(macOS 10.12, *)
|
||||||
|
public func sectionBy<T>(_ sectionKeyPath: KeyPath<O, FieldContainer<O>.Coded<T>>) -> SectionMonitorChainBuilder<O> {
|
||||||
|
|
||||||
|
return self.sectionBy(O.meta[keyPath: sectionKeyPath].keyPath, { $0 })
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Creates a `SectionMonitorChainBuilder` with the key path to use to group `ListMonitor` objects into sections
|
Creates a `SectionMonitorChainBuilder` with the key path to use to group `ListMonitor` objects into sections
|
||||||
@@ -416,6 +428,48 @@ extension From where O: CoreStoreObject {
|
|||||||
|
|
||||||
return self.sectionBy(O.meta[keyPath: sectionKeyPath].keyPath, { $0 })
|
return self.sectionBy(O.meta[keyPath: sectionKeyPath].keyPath, { $0 })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates a `SectionMonitorChainBuilder` with the key path to use to group `ListMonitor` objects into sections, and a closure to transform the value for the key path to an appropriate section name
|
||||||
|
|
||||||
|
- Important: Some utilities (such as `ListMonitor`s) may keep `SectionBy`s in memory and may thus introduce retain cycles if reference captures are not handled properly.
|
||||||
|
- parameter sectionKeyPath: the `KeyPath` to use to group the objects into sections
|
||||||
|
- parameter sectionIndexTransformer: a closure to transform the value for the key path to an appropriate section name
|
||||||
|
- returns: a `SectionMonitorChainBuilder` that is sectioned by the specified key path
|
||||||
|
*/
|
||||||
|
@available(macOS 10.12, *)
|
||||||
|
public func sectionBy<T>(_ sectionKeyPath: KeyPath<O, FieldContainer<O>.Stored<T>>, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) -> SectionMonitorChainBuilder<O> {
|
||||||
|
|
||||||
|
return self.sectionBy(O.meta[keyPath: sectionKeyPath].keyPath, sectionIndexTransformer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates a `SectionMonitorChainBuilder` with the key path to use to group `ListMonitor` objects into sections, and a closure to transform the value for the key path to an appropriate section name
|
||||||
|
|
||||||
|
- Important: Some utilities (such as `ListMonitor`s) may keep `SectionBy`s in memory and may thus introduce retain cycles if reference captures are not handled properly.
|
||||||
|
- parameter sectionKeyPath: the `KeyPath` to use to group the objects into sections
|
||||||
|
- parameter sectionIndexTransformer: a closure to transform the value for the key path to an appropriate section name
|
||||||
|
- returns: a `SectionMonitorChainBuilder` that is sectioned by the specified key path
|
||||||
|
*/
|
||||||
|
@available(macOS 10.12, *)
|
||||||
|
public func sectionBy<T>(_ sectionKeyPath: KeyPath<O, FieldContainer<O>.Virtual<T>>, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) -> SectionMonitorChainBuilder<O> {
|
||||||
|
|
||||||
|
return self.sectionBy(O.meta[keyPath: sectionKeyPath].keyPath, sectionIndexTransformer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates a `SectionMonitorChainBuilder` with the key path to use to group `ListMonitor` objects into sections, and a closure to transform the value for the key path to an appropriate section name
|
||||||
|
|
||||||
|
- Important: Some utilities (such as `ListMonitor`s) may keep `SectionBy`s in memory and may thus introduce retain cycles if reference captures are not handled properly.
|
||||||
|
- parameter sectionKeyPath: the `KeyPath` to use to group the objects into sections
|
||||||
|
- parameter sectionIndexTransformer: a closure to transform the value for the key path to an appropriate section name
|
||||||
|
- returns: a `SectionMonitorChainBuilder` that is sectioned by the specified key path
|
||||||
|
*/
|
||||||
|
@available(macOS 10.12, *)
|
||||||
|
public func sectionBy<T>(_ sectionKeyPath: KeyPath<O, FieldContainer<O>.Coded<T>>, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) -> SectionMonitorChainBuilder<O> {
|
||||||
|
|
||||||
|
return self.sectionBy(O.meta[keyPath: sectionKeyPath].keyPath, sectionIndexTransformer)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Creates a `SectionMonitorChainBuilder` with the key path to use to group `ListMonitor` objects into sections, and a closure to transform the value for the key path to an appropriate section name
|
Creates a `SectionMonitorChainBuilder` with the key path to use to group `ListMonitor` objects into sections, and a closure to transform the value for the key path to an appropriate section name
|
||||||
|
|||||||
@@ -106,6 +106,36 @@ extension SectionBy where O: NSManagedObject {
|
|||||||
|
|
||||||
@available(macOS 10.12, *)
|
@available(macOS 10.12, *)
|
||||||
extension SectionBy where O: CoreStoreObject {
|
extension SectionBy where O: CoreStoreObject {
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initializes a `SectionBy` clause with the key path to use to group `ListMonitor` objects into sections
|
||||||
|
|
||||||
|
- parameter sectionKeyPath: the key path to use to group the objects into sections
|
||||||
|
*/
|
||||||
|
public init<T>(_ sectionKeyPath: KeyPath<O, FieldContainer<O>.Stored<T>>) {
|
||||||
|
|
||||||
|
self.init(sectionKeyPath, { $0 })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initializes a `SectionBy` clause with the key path to use to group `ListMonitor` objects into sections
|
||||||
|
|
||||||
|
- parameter sectionKeyPath: the key path to use to group the objects into sections
|
||||||
|
*/
|
||||||
|
public init<T>(_ sectionKeyPath: KeyPath<O, FieldContainer<O>.Virtual<T>>) {
|
||||||
|
|
||||||
|
self.init(sectionKeyPath, { $0 })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initializes a `SectionBy` clause with the key path to use to group `ListMonitor` objects into sections
|
||||||
|
|
||||||
|
- parameter sectionKeyPath: the key path to use to group the objects into sections
|
||||||
|
*/
|
||||||
|
public init<T>(_ sectionKeyPath: KeyPath<O, FieldContainer<O>.Coded<T>>) {
|
||||||
|
|
||||||
|
self.init(sectionKeyPath, { $0 })
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initializes a `SectionBy` clause with the key path to use to group `ListMonitor` objects into sections
|
Initializes a `SectionBy` clause with the key path to use to group `ListMonitor` objects into sections
|
||||||
@@ -158,6 +188,42 @@ extension SectionBy where O: CoreStoreObject {
|
|||||||
|
|
||||||
self.init(O.meta[keyPath: sectionKeyPath].keyPath, sectionIndexTransformer)
|
self.init(O.meta[keyPath: sectionKeyPath].keyPath, sectionIndexTransformer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initializes a `SectionBy` clause with the key path to use to group `ListMonitor` objects into sections, and a closure to transform the value for the key path to an appropriate section name
|
||||||
|
|
||||||
|
- Important: Some utilities (such as `ListMonitor`s) may keep `SectionBy`s in memory and may thus introduce retain cycles if reference captures are not handled properly.
|
||||||
|
- parameter sectionKeyPath: the key path to use to group the objects into sections
|
||||||
|
- parameter sectionIndexTransformer: a closure to transform the value for the key path to an appropriate section name
|
||||||
|
*/
|
||||||
|
public init<T>(_ sectionKeyPath: KeyPath<O, FieldContainer<O>.Stored<T>>, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) {
|
||||||
|
|
||||||
|
self.init(O.meta[keyPath: sectionKeyPath].keyPath, sectionIndexTransformer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initializes a `SectionBy` clause with the key path to use to group `ListMonitor` objects into sections, and a closure to transform the value for the key path to an appropriate section name
|
||||||
|
|
||||||
|
- Important: Some utilities (such as `ListMonitor`s) may keep `SectionBy`s in memory and may thus introduce retain cycles if reference captures are not handled properly.
|
||||||
|
- parameter sectionKeyPath: the key path to use to group the objects into sections
|
||||||
|
- parameter sectionIndexTransformer: a closure to transform the value for the key path to an appropriate section name
|
||||||
|
*/
|
||||||
|
public init<T>(_ sectionKeyPath: KeyPath<O, FieldContainer<O>.Virtual<T>>, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) {
|
||||||
|
|
||||||
|
self.init(O.meta[keyPath: sectionKeyPath].keyPath, sectionIndexTransformer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initializes a `SectionBy` clause with the key path to use to group `ListMonitor` objects into sections, and a closure to transform the value for the key path to an appropriate section name
|
||||||
|
|
||||||
|
- Important: Some utilities (such as `ListMonitor`s) may keep `SectionBy`s in memory and may thus introduce retain cycles if reference captures are not handled properly.
|
||||||
|
- parameter sectionKeyPath: the key path to use to group the objects into sections
|
||||||
|
- parameter sectionIndexTransformer: a closure to transform the value for the key path to an appropriate section name
|
||||||
|
*/
|
||||||
|
public init<T>(_ sectionKeyPath: KeyPath<O, FieldContainer<O>.Coded<T>>, _ sectionIndexTransformer: @escaping (_ sectionName: String?) -> String?) {
|
||||||
|
|
||||||
|
self.init(O.meta[keyPath: sectionKeyPath].keyPath, sectionIndexTransformer)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initializes a `SectionBy` clause with the key path to use to group `ListMonitor` objects into sections, and a closure to transform the value for the key path to an appropriate section name
|
Initializes a `SectionBy` clause with the key path to use to group `ListMonitor` objects into sections, and a closure to transform the value for the key path to an appropriate section name
|
||||||
|
|||||||
Reference in New Issue
Block a user