Compare commits

...

34 Commits

Author SHA1 Message Date
John Estropia
496145761a version bump 2021-09-22 20:30:40 +09:00
John Estropia
c54795db5a project cleanup 2021-09-22 20:09:32 +09:00
John Estropia
9a026afe40 goodbye ObjectiveC 2021-09-22 20:04:58 +09:00
John Estropia
bf10f4668c revert Objc method changes 2021-09-22 15:03:46 +09:00
John Estropia
a1a04aaf8a tag refetch methods with source identifiers 2021-09-15 19:38:59 +09:00
John Estropia
4ddfa95140 added mechanism to track transaction sources 2021-09-15 14:45:13 +09:00
John Estropia
45215c7a18 WIP 2021-08-25 20:13:14 +09:00
John Estropia
d2f1656fdd test copy-on-write for ListSnapshot 2021-08-25 09:37:20 +09:00
John Estropia
5fbb1ab09d Merge pull request #421 from xquezme/develop
Fix compound indexes for dynamic models
2021-07-20 09:26:17 +09:00
John Estropia
d0cc01877e Merge pull request #433 from tackgyu/unset-library-type
Unset library type in Swift package manifests
2021-07-19 13:35:39 +09:00
tackgyu
a434628249 Unset library type in Swift package manifests 2021-07-19 12:52:51 +09:00
John Estropia
9cc616f720 fix compiler error on Xcode 13 2021-06-19 15:49:45 +09:00
John Estropia
4534bc06f5 Add utility for DiffableDataSources to create an empty snapshot for custom list construction 2021-06-16 23:28:46 +09:00
John Estropia
798d30bbd9 allow ListPublisher and ObjectPublisher combine Publishers to cancel subscription from any thread 2021-06-13 14:36:22 +09:00
John Estropia
7938aa2447 Added fast index-based ListSnapshot mutators 2021-06-12 11:06:43 +09:00
John Estropia
dda69389eb Fix SPM issues 2021-04-20 18:30:14 +09:00
John Estropia
b20be10a19 update Readme banner image 2021-04-11 11:39:43 +09:00
John Estropia
0ee8fbabd5 version bump, update resources 2021-04-11 11:26:02 +09:00
John Estropia
1f562b25a7 Updated README 2021-04-11 11:03:17 +09:00
Pimenov Sergey
6a2394052c fix compound indexes for dynamic models 2021-04-04 20:12:40 -07:00
John Estropia
593c0510d3 Allow placeholder Views in ObjectReader when an object becomes nil 2021-03-13 11:25:27 +09:00
John Estropia
338e4ddc9f Fix sig abort error 2021-03-07 17:02:09 +09:00
John Estropia
bfb1df3c40 added Publishers for addStorage functions 2021-03-07 16:08:19 +09:00
John Estropia
003bf897e2 Cleanup unnecessary #available branches 2021-03-07 12:01:08 +09:00
John Estropia
0b127956d3 Removed ObservableObject implementations of ListPublisher/ObjectPublisher in favor of LiveList/LiveObject and ".reactive" publishers 2021-03-07 10:38:53 +09:00
John Estropia
098e560fcc Merge branch 'develop' of github.com:JohnEstropia/CoreStore into develop 2021-03-07 10:17:34 +09:00
John Estropia
7dbd3777ec added sugar syntax for ForEach that removes requirement for the "id:" argument 2021-03-07 10:17:20 +09:00
John Estropia
447d8e5880 fix compile error 2021-03-03 16:59:20 +09:00
John Estropia
1f97225efa SwiftUI and Combine utilities appledocs. Bump up to 8.0 and iOS 11.0/macOS 10.13 2021-03-01 09:14:41 +09:00
John Estropia
d13b0cfabb update unit tests 2021-02-21 10:59:55 +09:00
John Estropia
d7b852fca4 SwiftUI utilities done (for now) 2021-02-21 10:56:27 +09:00
John Estropia
f2efe175e5 deprecate misleading API for sectionIndexTransformers 2021-02-21 10:17:58 +09:00
John Estropia
8f3a6638d8 Delete long-deprecated CoreStore namespace 2021-02-21 10:16:08 +09:00
John Estropia
f7471f56a4 Prototyping SwiftUI utilities 2021-02-16 09:12:36 +09:00
221 changed files with 7053 additions and 13283 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = "CoreStore"
s.version = "7.3.1"
s.swift_version = "5.3"
s.version = "8.1.0"
s.swift_version = "5.5"
s.license = "MIT"
s.homepage = "https://github.com/JohnEstropia/CoreStore"
s.documentation_url = "https://JohnEstropia.github.io/CoreStore"
@@ -9,10 +9,10 @@ Pod::Spec.new do |s|
s.author = { "John Rommel Estropia" => "rommel.estropia@gmail.com" }
s.source = { :git => "https://github.com/JohnEstropia/CoreStore.git", :tag => s.version.to_s }
s.ios.deployment_target = "10.0"
s.osx.deployment_target = "10.12"
s.watchos.deployment_target = "3.0"
s.tvos.deployment_target = "10.0"
s.ios.deployment_target = "11.0"
s.osx.deployment_target = "10.13"
s.watchos.deployment_target = "4.0"
s.tvos.deployment_target = "11.0"
s.source_files = "Sources", "Sources/**/*.{swift,h,m}"
s.public_header_files = "Sources/**/*.h"

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1200"
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1200"
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1200"
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1200"
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@@ -7,7 +7,4 @@
<FileRef
location = "group:CoreStore.xcodeproj">
</FileRef>
<FileRef
location = "group:LegacyDemo/LegacyDemo.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -1,30 +0,0 @@
//
// BridgingTests.h
// CoreStore
//
// Copyright © 2018 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#import <XCTest/XCTest.h>
@interface BridgingTests : XCTestCase
@end

View File

@@ -1,269 +0,0 @@
//
// BridgingTests.m
// CoreStore
//
// Copyright © 2018 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#import "BridgingTests.h"
#import <CoreStore/CoreStore.h>
#import <CoreStore/CoreStore-Swift.h>
#import "CoreStoreTests-Swift.h"
@import CoreData;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
// MARK: - BridgingTests
@implementation BridgingTests
- (void)test_ThatFlags_HaveCorrectValues {
XCTAssertEqual(CSLocalStorageOptionsNone, 0);
XCTAssertEqual(CSLocalStorageOptionsRecreateStoreOnModelMismatch, 1);
XCTAssertEqual(CSLocalStorageOptionsPreventProgressiveMigration, 2);
XCTAssertEqual(CSLocalStorageOptionsAllowSynchronousLightweightMigration, 4);
}
- (void)test_ThatKeyPaths_AreCorrect {
XCTAssertEqualObjects(CSKeyPath(TestEntity1, testNumber), @"testNumber");
XCTAssertEqualObjects(CSKeyPath(TestEntity1, testString), @"testString");
XCTAssertEqualObjects(CSKeyPathOperator(count, TestEntity1, testString), @"@count.testString");
XCTAssertEqualObjects(CSKeyPathOperator(max, TestEntity1, testNumber), @"@max.testNumber");
}
- (void)test_ThatFromClauses_BridgeCorrectly {
{
CSFrom *from = CSFromClass([TestEntity1 class]);
XCTAssertEqualObjects(from.entityClass, [TestEntity1 class]);
XCTAssertNil(from.configurations);
}
{
CSFrom *from = CSFromClass([TestEntity1 class], [NSNull null]);
XCTAssertEqualObjects(from.entityClass, [TestEntity1 class]);
NSArray *configurations = @[[NSNull null]];
XCTAssertEqualObjects(from.configurations, configurations);
}
{
CSFrom *from = CSFromClass([TestEntity1 class], @"Config1");
XCTAssertEqualObjects(from.entityClass, [TestEntity1 class]);
NSArray *configurations = @[@"Config1"];
XCTAssertEqualObjects(from.configurations, configurations);
}
{
CSFrom *from = CSFromClass([TestEntity1 class], @[[NSNull null], @"Config2"]);
XCTAssertEqualObjects(from.entityClass, [TestEntity1 class]);
NSArray *configurations = @[[NSNull null], @"Config2"];
XCTAssertEqualObjects(from.configurations, configurations);
}
}
- (void)test_ThatWhereClauses_BridgeCorrectly {
{
CSWhere *where = CSWhereFormat(@"%K == %@", @"key", @"value");
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@", @"key", @"value"];
XCTAssertEqualObjects(where.predicate, predicate);
}
{
CSWhere *where = CSWhereValue(YES);
NSPredicate *predicate = [NSPredicate predicateWithValue:YES];
XCTAssertEqualObjects(where.predicate, predicate);
}
{
CSWhere *where = CSWherePredicate([NSPredicate predicateWithFormat:@"%K == %@", @"key", @"value"]);
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@", @"key", @"value"];
XCTAssertEqualObjects(where.predicate, predicate);
}
}
- (void)test_ThatOrderByClauses_BridgeCorrectly {
{
CSOrderBy *orderBy = CSOrderByKey(CSSortAscending(@"key"));
XCTAssertEqualObjects(orderBy.sortDescriptors, @[[NSSortDescriptor sortDescriptorWithKey:@"key" ascending:YES]]);
}
{
CSOrderBy *orderBy = CSOrderByKey(CSSortDescending(@"key"));
XCTAssertEqualObjects(orderBy.sortDescriptors, @[[NSSortDescriptor sortDescriptorWithKey:@"key" ascending:NO]]);
}
{
CSOrderBy *orderBy = CSOrderByKeys(CSSortAscending(@"key1"), CSSortDescending(@"key2"), nil);
NSArray *sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"key1" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:@"key2" ascending:NO]];
XCTAssertEqualObjects(orderBy.sortDescriptors, sortDescriptors);
}
}
- (void)test_ThatGroupByClauses_BridgeCorrectly {
{
CSGroupBy *groupBy = CSGroupByKeyPath(@"key");
XCTAssertEqualObjects(groupBy.keyPaths, @[@"key"]);
}
{
CSGroupBy *groupBy = CSGroupByKeyPaths(@[@"key1", @"key2"]);
NSArray *keyPaths = @[@"key1", @"key2"];
XCTAssertEqualObjects(groupBy.keyPaths, keyPaths);
}
}
- (void)test_ThatTweakClauses_BridgeCorrectly {
CSTweak *tweak = CSTweakRequest(^(NSFetchRequest * _Nonnull fetchRequest) {
fetchRequest.fetchLimit = 100;
});
NSFetchRequest *request = [NSFetchRequest new];
tweak.block(request);
XCTAssertEqual(request.fetchLimit, 100);
}
- (void)test_ThatIntoClauses_BridgeCorrectly {
{
CSInto *into = CSIntoClass([TestEntity1 class]);
XCTAssertEqualObjects(into.entityClass, [TestEntity1 class]);
}
{
CSInto *into = CSIntoClass([TestEntity1 class], [NSNull null]);
XCTAssertEqualObjects(into.entityClass, [TestEntity1 class]);
XCTAssertNil(into.configuration);
}
{
CSInto *into = CSIntoClass([TestEntity1 class], @"Config1");
XCTAssertEqualObjects(into.entityClass, [TestEntity1 class]);
XCTAssertEqualObjects(into.configuration, @"Config1");
}
}
- (void)test_ThatDataStacks_BridgeCorrectly {
CSDataStack *dataStack = [[CSDataStack alloc]
initWithXcodeModelName:@"Model"
bundle:[NSBundle bundleForClass:[self class]]
versionChain:nil];
XCTAssertNotNil(dataStack);
NSError *memoryError;
CSInMemoryStore *memoryStorage = [dataStack
addInMemoryStorageAndWait:[CSInMemoryStore new]
error:&memoryError];
XCTAssertNotNil(memoryStorage);
XCTAssertEqualObjects([[memoryStorage class] storeType], [CSInMemoryStore storeType]);
XCTAssertEqualObjects([[memoryStorage class] storeType], NSInMemoryStoreType);
XCTAssertNil(memoryStorage.configuration);
XCTAssertNil(memoryStorage.storeOptions);
XCTAssertNil(memoryError);
NSError *sqliteError;
CSSQLiteStore *sqliteStorage = [dataStack
addSQLiteStorageAndWait:[CSSQLiteStore new]
error:&sqliteError];
XCTAssertNotNil(sqliteStorage);
XCTAssertEqualObjects([[sqliteStorage class] storeType], [CSSQLiteStore storeType]);
XCTAssertEqualObjects([[sqliteStorage class] storeType], NSSQLiteStoreType);
XCTAssertNil(sqliteStorage.configuration);
NSDictionary *storeOptions;
if (@available(iOS 11.0, macOS 10.13, tvOS 11.0, *)) {
storeOptions = @{ NSSQLitePragmasOption: @{ @"journal_mode": @"WAL" },
NSBinaryStoreInsecureDecodingCompatibilityOption: @YES };
}
else {
storeOptions = @{ NSSQLitePragmasOption: @{ @"journal_mode": @"WAL" }};
}
XCTAssertEqualObjects(sqliteStorage.storeOptions, storeOptions);
XCTAssertNil(sqliteError);
}
- (void)test_ThatTransactions_BridgeCorrectly {
CSDataStack *dataStack = [[CSDataStack alloc]
initWithXcodeModelName:@"Model"
bundle:[NSBundle bundleForClass:[self class]]
versionChain:nil];
XCTAssertNotNil(dataStack);
[dataStack
addInMemoryStorageAndWait:[CSInMemoryStore new]
error:nil];
{
CSUnsafeDataTransaction *transaction = [dataStack beginUnsafe];
XCTAssertNotNil(transaction);
XCTAssert([transaction isKindOfClass:[CSUnsafeDataTransaction class]]);
NSError *error;
BOOL result = [transaction commitAndWaitWithError:&error];
XCTAssertTrue(result);
XCTAssertNil(error);
}
{
XCTestExpectation *expectation = [self expectationWithDescription:@"sync"];
NSError *error;
BOOL result =
[dataStack
beginSynchronous:^(CSSynchronousDataTransaction * _Nonnull transaction) {
XCTAssertNotNil(transaction);
XCTAssert([transaction isKindOfClass:[CSSynchronousDataTransaction class]]);
NSError *error;
XCTAssertTrue([transaction commitAndWaitWithError:&error]);
XCTAssertNil(error);
[expectation fulfill];
}
error:&error];
XCTAssertTrue(result);
XCTAssertNil(error);
}
{
XCTestExpectation *expectation = [self expectationWithDescription:@"async"];
[dataStack beginAsynchronous:^(CSAsynchronousDataTransaction * _Nonnull transaction) {
XCTAssertNotNil(transaction);
XCTAssert([transaction isKindOfClass:[CSAsynchronousDataTransaction class]]);
[transaction
commitWithSuccess:^{
[expectation fulfill];
}
failure:^(CSError *error){
XCTFail();
}];
}];
}
[self waitForExpectationsWithTimeout:10 handler:nil];
}
@end
#pragma clang diagnostic pop

View File

@@ -23,13 +23,15 @@
// SOFTWARE.
//
import CoreData
import XCTest
@testable
import CoreStore
// MARK: - ConvenienceTests
@available(macOS 10.12, *)
class ConvenienceTests: BaseTestCase {
@objc

View File

@@ -1,5 +0,0 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "BridgingTests.h"

View File

@@ -197,7 +197,7 @@ class DynamicModelTests: BaseTestDataTestCase {
modelVersion: "V1",
entities: [
Entity<Animal>("Animal"),
Entity<Dog>("Dog"),
Entity<Dog>("Dog", indexes: [[\Dog.$nickname, \Dog.$age]]),
Entity<Person>("Person")
],
versionLock: [

View File

@@ -31,7 +31,6 @@ import CoreStore
// MARK: - ErrorTests
@available(*, deprecated, message: "CoreStore Objective-C API will be removed soon.")
final class ErrorTests: XCTestCase {
@objc
@@ -43,14 +42,12 @@ final class ErrorTests: XCTestCase {
let userInfo: NSDictionary = [:]
let objcError = error.bridgeToObjectiveC
XCTAssertEqual(error, objcError.bridgeToSwift)
let objcError = error as NSError
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.unknownError.rawValue)
XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC
XCTAssertEqual(error, objcError2.bridgeToSwift)
let objcError2 = CoreStoreError(objcError) as NSError
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.unknownError.rawValue)
XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
@@ -68,14 +65,12 @@ final class ErrorTests: XCTestCase {
let userInfo: NSDictionary = [
"existingPersistentStoreURL": dummyURL
]
let objcError = error.bridgeToObjectiveC
XCTAssertEqual(error, objcError.bridgeToSwift)
let objcError = error as NSError
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.differentStorageExistsAtURL.rawValue)
XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC
XCTAssertEqual(error, objcError2.bridgeToSwift)
let objcError2 = CoreStoreError(objcError) as NSError
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.differentStorageExistsAtURL.rawValue)
XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
@@ -103,14 +98,12 @@ final class ErrorTests: XCTestCase {
"targetModel": schemaHistory.rawModel,
"targetModelVersion": version
]
let objcError = error.bridgeToObjectiveC
XCTAssertEqual(error, objcError.bridgeToSwift)
let objcError = error as NSError
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.mappingModelNotFound.rawValue)
XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC
XCTAssertEqual(error, objcError2.bridgeToSwift)
let objcError2 = CoreStoreError(objcError) as NSError
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.mappingModelNotFound.rawValue)
XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
@@ -128,14 +121,12 @@ final class ErrorTests: XCTestCase {
let userInfo: NSDictionary = [
"localStoreURL": dummyURL
]
let objcError = error.bridgeToObjectiveC
XCTAssertEqual(error, objcError.bridgeToSwift)
let objcError = error as NSError
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.progressiveMigrationRequired.rawValue)
XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC
XCTAssertEqual(error, objcError2.bridgeToSwift)
let objcError2 = CoreStoreError(objcError) as NSError
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.progressiveMigrationRequired.rawValue)
XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)
@@ -160,14 +151,12 @@ final class ErrorTests: XCTestCase {
let userInfo: NSDictionary = [
"NSError": internalError
]
let objcError = error.bridgeToObjectiveC
XCTAssertEqual(error, objcError.bridgeToSwift)
let objcError = error as NSError
XCTAssertEqual(objcError.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError.code, CoreStoreErrorCode.internalError.rawValue)
XCTAssertEqual(objcError.userInfo as NSDictionary, userInfo)
let objcError2 = objcError.bridgeToSwift.bridgeToObjectiveC
XCTAssertEqual(error, objcError2.bridgeToSwift)
let objcError2 = CoreStoreError(objcError) as NSError
XCTAssertEqual(objcError2.domain, CoreStoreErrorDomain)
XCTAssertEqual(objcError2.code, CoreStoreErrorCode.internalError.rawValue)
XCTAssertEqual(objcError2.userInfo as NSDictionary, userInfo)

View File

@@ -23,6 +23,7 @@
// SOFTWARE.
//
import CoreData
import XCTest
@testable

View File

@@ -23,6 +23,7 @@
// SOFTWARE.
//
import CoreData
import XCTest
@testable

View File

@@ -23,6 +23,7 @@
// SOFTWARE.
//
import CoreData
import XCTest
@testable
@@ -125,15 +126,4 @@ final class IntoTests: XCTestCase {
XCTAssertNotEqual(into, Into<TestEntity1>("Config2"))
}
}
@objc
dynamic func test_ThatIntoClauses_BridgeCorrectly() {
do {
let into = Into<NSManagedObject>()
let objcInto = into.bridgeToObjectiveC
XCTAssertEqual(into, objcInto.bridgeToSwift)
}
}
}

View File

@@ -23,6 +23,7 @@
// SOFTWARE.
//
import CoreData
import XCTest
@testable
@@ -31,7 +32,6 @@ import CoreStore
// MARK: - ListObserverTests
@available(macOS 10.12, *)
class ListObserverTests: BaseTestDataTestCase {
@objc
@@ -551,7 +551,6 @@ class ListObserverTests: BaseTestDataTestCase {
// MARK: TestListObserver
@available(macOS 10.12, *)
class TestListObserver: ListSectionObserver {
// MARK: ListObserver

View File

@@ -31,7 +31,6 @@ import CoreStore
// MARK: - ObjectObserverTests
@available(macOS 10.12, *)
class ObjectObserverTests: BaseTestDataTestCase {
@objc
@@ -203,7 +202,6 @@ class ObjectObserverTests: BaseTestDataTestCase {
// MARK: TestObjectObserver
@available(macOS 10.12, *)
class TestObjectObserver: ObjectObserver {
typealias ObjectEntityType = TestEntity1

View File

@@ -31,7 +31,6 @@ import CoreStore
// MARK: - ObjectPublisherTests
@available(macOS 10.12, *)
class ObjectPublisherTests: BaseTestDataTestCase {
@objc

View File

@@ -23,6 +23,7 @@
// SOFTWARE.
//
import CoreData
import XCTest
@testable

View File

@@ -23,6 +23,7 @@
// SOFTWARE.
//
import CoreData
import XCTest
@testable

View File

@@ -23,6 +23,7 @@
// SOFTWARE.
//
import CoreData
import XCTest
@testable
@@ -31,7 +32,6 @@ import CoreStore
//MARK: - SectionByTests
@available(macOS 10.12, *)
final class SectionByTests: XCTestCase {
@objc
@@ -41,11 +41,14 @@ final class SectionByTests: XCTestCase {
let sectionBy = SectionBy<NSManagedObject>("key")
XCTAssertEqual(sectionBy.sectionKeyPath, "key")
XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key")
XCTAssertNil(sectionBy.sectionIndexTransformer("key"))
}
do {
let sectionBy = SectionBy<NSManagedObject>("key") { $0.flatMap { "\($0):suffix" } }
let sectionBy = SectionBy<NSManagedObject>(
"key",
sectionIndexTransformer: { $0.flatMap { "\($0):suffix" } }
)
XCTAssertEqual(sectionBy.sectionKeyPath, "key")
XCTAssertEqual(sectionBy.sectionIndexTransformer("key"), "key:suffix")
XCTAssertNil(sectionBy.sectionIndexTransformer(nil))

View File

@@ -23,6 +23,7 @@
// SOFTWARE.
//
import CoreData
import XCTest
@testable

View File

@@ -23,6 +23,9 @@
// SOFTWARE.
//
import CoreData
import XCTest
@testable
import CoreStore

View File

@@ -23,6 +23,7 @@
// SOFTWARE.
//
import CoreData
import XCTest
@testable
@@ -83,21 +84,11 @@ final class StorageInterfaceTests: XCTestCase {
let store = SQLiteStore()
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
XCTAssertNil(store.configuration)
if #available(iOS 11.0, macOS 10.13, tvOS 11.0, *) {
XCTAssertEqual(
store.storeOptions as NSDictionary?,
[NSSQLitePragmasOption: ["journal_mode": "WAL"],
NSBinaryStoreInsecureDecodingCompatibilityOption: true] as NSDictionary
)
}
else {
XCTAssertEqual(
store.storeOptions as NSDictionary?,
[NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary
)
}
XCTAssertEqual(
store.storeOptions as NSDictionary?,
[NSSQLitePragmasOption: ["journal_mode": "WAL"],
NSBinaryStoreInsecureDecodingCompatibilityOption: true] as NSDictionary
)
XCTAssertEqual(store.fileURL, SQLiteStore.defaultFileURL)
XCTAssertTrue(store.migrationMappingProviders.isEmpty)
@@ -123,21 +114,11 @@ final class StorageInterfaceTests: XCTestCase {
)
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
XCTAssertEqual(store.configuration, "config1")
if #available(iOS 11.0, macOS 10.13, tvOS 11.0, *) {
XCTAssertEqual(
store.storeOptions as NSDictionary?,
[NSSQLitePragmasOption: ["journal_mode": "WAL"],
NSBinaryStoreInsecureDecodingCompatibilityOption: true] as NSDictionary
)
}
else {
XCTAssertEqual(
store.storeOptions as NSDictionary?,
[NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary
)
}
XCTAssertEqual(
store.storeOptions as NSDictionary?,
[NSSQLitePragmasOption: ["journal_mode": "WAL"],
NSBinaryStoreInsecureDecodingCompatibilityOption: true] as NSDictionary
)
XCTAssertEqual(store.fileURL, fileURL)
XCTAssertEqual(store.migrationMappingProviders as! [XcodeSchemaMappingProvider], [mappingProvider])
@@ -160,21 +141,11 @@ final class StorageInterfaceTests: XCTestCase {
)
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
XCTAssertEqual(store.configuration, "config1")
if #available(iOS 11.0, macOS 10.13, tvOS 11.0, *) {
XCTAssertEqual(
store.storeOptions as NSDictionary?,
[NSSQLitePragmasOption: ["journal_mode": "WAL"],
NSBinaryStoreInsecureDecodingCompatibilityOption: true] as NSDictionary
)
}
else {
XCTAssertEqual(
store.storeOptions as NSDictionary?,
[NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary
)
}
XCTAssertEqual(
store.storeOptions as NSDictionary?,
[NSSQLitePragmasOption: ["journal_mode": "WAL"],
NSBinaryStoreInsecureDecodingCompatibilityOption: true] as NSDictionary
)
XCTAssertEqual(store.fileURL.deletingLastPathComponent(), SQLiteStore.defaultRootDirectory)
XCTAssertEqual(store.fileURL.lastPathComponent, fileName)
@@ -209,21 +180,11 @@ final class StorageInterfaceTests: XCTestCase {
let store = SQLiteStore.legacy()
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
XCTAssertNil(store.configuration)
if #available(iOS 11.0, macOS 10.13, tvOS 11.0, *) {
XCTAssertEqual(
store.storeOptions as NSDictionary?,
[NSSQLitePragmasOption: ["journal_mode": "WAL"],
NSBinaryStoreInsecureDecodingCompatibilityOption: true] as NSDictionary
)
}
else {
XCTAssertEqual(
store.storeOptions as NSDictionary?,
[NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary
)
}
XCTAssertEqual(
store.storeOptions as NSDictionary?,
[NSSQLitePragmasOption: ["journal_mode": "WAL"],
NSBinaryStoreInsecureDecodingCompatibilityOption: true] as NSDictionary
)
XCTAssertEqual(store.fileURL, SQLiteStore.legacyDefaultFileURL)
XCTAssertTrue(store.migrationMappingProviders.isEmpty)
@@ -246,21 +207,11 @@ final class StorageInterfaceTests: XCTestCase {
)
XCTAssertEqual(type(of: store).storeType, NSSQLiteStoreType)
XCTAssertEqual(store.configuration, "config1")
if #available(iOS 11.0, macOS 10.13, tvOS 11.0, *) {
XCTAssertEqual(
store.storeOptions as NSDictionary?,
[NSSQLitePragmasOption: ["journal_mode": "WAL"],
NSBinaryStoreInsecureDecodingCompatibilityOption: true] as NSDictionary
)
}
else {
XCTAssertEqual(
store.storeOptions as NSDictionary?,
[NSSQLitePragmasOption: ["journal_mode": "WAL"]] as NSDictionary
)
}
XCTAssertEqual(
store.storeOptions as NSDictionary?,
[NSSQLitePragmasOption: ["journal_mode": "WAL"],
NSBinaryStoreInsecureDecodingCompatibilityOption: true] as NSDictionary
)
XCTAssertEqual(store.fileURL.deletingLastPathComponent(), SQLiteStore.legacyDefaultRootDirectory)
XCTAssertEqual(store.fileURL.lastPathComponent, fileName)

View File

@@ -383,8 +383,6 @@ final class TransactionTests: BaseTestCase {
}
}
@available(macOS 10.12, *)
@objc
dynamic func test_ThatSynchronousTransactions_CanCommitWithoutWaitingForMerges() {

View File

@@ -23,6 +23,7 @@
// SOFTWARE.
//
import CoreData
import XCTest
@testable

View File

@@ -23,6 +23,7 @@
// SOFTWARE.
//
import CoreData
import XCTest
@testable

View File

@@ -15,9 +15,9 @@
B54D2F7C251196B6004BEC7D /* Advanced.EvolutionDemo.V2.FromV1MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54D2F7B251196B6004BEC7D /* Advanced.EvolutionDemo.V2.FromV1MigrationPolicy.swift */; };
B54D2F7E25119DCE004BEC7D /* Advanced.EvolutionDemo.V1.FromV2.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = B54D2F7D25119DCE004BEC7D /* Advanced.EvolutionDemo.V1.FromV2.xcmappingmodel */; };
B54D2F852511B70B004BEC7D /* Advanced.EvolutionDemo.CreaturesDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54D2F842511B70B004BEC7D /* Advanced.EvolutionDemo.CreaturesDataSource.swift */; };
B566C8E824F9D406001134A1 /* Modern.PokedexDemo.ListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566C8E724F9D406001134A1 /* Modern.PokedexDemo.ListView.swift */; };
B566C8EA24F9D412001134A1 /* Modern.PokedexDemo.ListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566C8E924F9D412001134A1 /* Modern.PokedexDemo.ListViewController.swift */; };
B566C8EC24F9D694001134A1 /* Modern.PokedexDemo.ItemCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566C8EB24F9D694001134A1 /* Modern.PokedexDemo.ItemCell.swift */; };
B566C8E824F9D406001134A1 /* Modern.PokedexDemo.UIKit.ListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566C8E724F9D406001134A1 /* Modern.PokedexDemo.UIKit.ListView.swift */; };
B566C8EA24F9D412001134A1 /* Modern.PokedexDemo.UIKit.ListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566C8E924F9D412001134A1 /* Modern.PokedexDemo.UIKit.ListViewController.swift */; };
B566C8EC24F9D694001134A1 /* Modern.PokedexDemo.UIKit.ItemCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566C8EB24F9D694001134A1 /* Modern.PokedexDemo.UIKit.ItemCell.swift */; };
B566C8EE24FA1EA3001134A1 /* Modern.PokedexDemo.Details.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566C8ED24FA1EA3001134A1 /* Modern.PokedexDemo.Details.swift */; };
B5931B4225124756007DA58E /* Advanced.EvolutionDemo.V1.FromV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5931B4125124756007DA58E /* Advanced.EvolutionDemo.V1.FromV2.swift */; };
B5931B442512480A007DA58E /* Advanced.EvolutionDemo.V2.FromV1.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5931B432512480A007DA58E /* Advanced.EvolutionDemo.V2.FromV1.swift */; };
@@ -41,12 +41,6 @@
B5A3916524E698C700E7E8BD /* Modern.PlacemarksDemo.Place.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A3916424E698C700E7E8BD /* Modern.PlacemarksDemo.Place.swift */; };
B5A3916B24E698F900E7E8BD /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916724E698F900E7E8BD /* CoreStore.framework */; };
B5A3916C24E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916724E698F900E7E8BD /* CoreStore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B5A3916D24E698F900E7E8BD /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916824E698F900E7E8BD /* CoreStore.framework */; };
B5A3916E24E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916824E698F900E7E8BD /* CoreStore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B5A3916F24E698F900E7E8BD /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916924E698F900E7E8BD /* CoreStore.framework */; };
B5A3917024E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916924E698F900E7E8BD /* CoreStore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B5A3917124E698F900E7E8BD /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916A24E698F900E7E8BD /* CoreStore.framework */; };
B5A3917224E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3916A24E698F900E7E8BD /* CoreStore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B5A3917524E6990200E7E8BD /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3917424E6990200E7E8BD /* MapKit.framework */; };
B5A3917724E6990700E7E8BD /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3917624E6990700E7E8BD /* CoreLocation.framework */; };
B5A3917924E6991600E7E8BD /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A3917824E6991600E7E8BD /* SwiftUI.framework */; };
@@ -68,7 +62,7 @@
B5A391A024E8F00A00E7E8BD /* Modern.ColorsDemo.UIKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A3919F24E8F00A00E7E8BD /* Modern.ColorsDemo.UIKit.swift */; };
B5A391A224E8F01F00E7E8BD /* ⭐Modern.ColorsDemo.UIKit.ListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A391A124E8F01F00E7E8BD /* ⭐Modern.ColorsDemo.UIKit.ListViewController.swift */; };
B5A391A424E8F04300E7E8BD /* Modern.ColorsDemo.UIKit.ListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A391A324E8F04300E7E8BD /* Modern.ColorsDemo.UIKit.ListView.swift */; };
B5A391A624E8F4EA00E7E8BD /* ⭐️Modern.ColorsDemo.MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A391A524E8F4EA00E7E8BD /* ⭐️Modern.ColorsDemo.MainView.swift */; };
B5A391A624E8F4EA00E7E8BD /* Modern.ColorsDemo.MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A391A524E8F4EA00E7E8BD /* Modern.ColorsDemo.MainView.swift */; };
B5A391AA24E9104300E7E8BD /* Modern.ColorsDemo.UIKit.ItemCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A391A924E9104300E7E8BD /* Modern.ColorsDemo.UIKit.ItemCell.swift */; };
B5A391AC24E9143B00E7E8BD /* Modern.ColorsDemo.UIKit.DetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A391AB24E9143B00E7E8BD /* Modern.ColorsDemo.UIKit.DetailView.swift */; };
B5A391AE24E9150F00E7E8BD /* ⭐Modern.ColorsDemo.UIKit.DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A391AD24E9150F00E7E8BD /* ⭐Modern.ColorsDemo.UIKit.DetailViewController.swift */; };
@@ -97,6 +91,7 @@
B5A5440B25049492000DC5E3 /* Advanced.EvolutionDemo.V3.Creature.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A5440A25049492000DC5E3 /* Advanced.EvolutionDemo.V3.Creature.swift */; };
B5A5440D2504949C000DC5E3 /* Advanced.EvolutionDemo.V4.Creature.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A5440C2504949C000DC5E3 /* Advanced.EvolutionDemo.V4.Creature.swift */; };
B5C18F3325138700001BEFB3 /* Advanced.EvolutionDemo.ProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C18F3225138700001BEFB3 /* Advanced.EvolutionDemo.ProgressView.swift */; };
B5C795B625D8EE2B00BDACC1 /* Modern.PokedexDemo.UIKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C795B525D8EE2B00BDACC1 /* Modern.PokedexDemo.UIKit.swift */; };
B5D6F1F8250E07FD00DF5D2F /* Advanced.EvolutionDemo.V1.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D6F1F7250E07FD00DF5D2F /* Advanced.EvolutionDemo.V1.swift */; };
B5D6F1FC250E0B1700DF5D2F /* Advanced.EvolutionDemo.V2.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D6F1FB250E0B1700DF5D2F /* Advanced.EvolutionDemo.V2.swift */; };
B5D6F1FE250E0B3F00DF5D2F /* Advanced.EvolutionDemo.GeologicalPeriod.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5D6F1FD250E0B3F00DF5D2F /* Advanced.EvolutionDemo.GeologicalPeriod.swift */; };
@@ -115,9 +110,6 @@
dstSubfolderSpec = 10;
files = (
B5A3916C24E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */,
B5A3917224E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */,
B5A3917024E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */,
B5A3916E24E698F900E7E8BD /* CoreStore.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@@ -133,9 +125,9 @@
B54D2F7B251196B6004BEC7D /* Advanced.EvolutionDemo.V2.FromV1MigrationPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.V2.FromV1MigrationPolicy.swift; sourceTree = "<group>"; };
B54D2F7D25119DCE004BEC7D /* Advanced.EvolutionDemo.V1.FromV2.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = Advanced.EvolutionDemo.V1.FromV2.xcmappingmodel; sourceTree = "<group>"; };
B54D2F842511B70B004BEC7D /* Advanced.EvolutionDemo.CreaturesDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.CreaturesDataSource.swift; sourceTree = "<group>"; };
B566C8E724F9D406001134A1 /* Modern.PokedexDemo.ListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.ListView.swift; sourceTree = "<group>"; };
B566C8E924F9D412001134A1 /* Modern.PokedexDemo.ListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.ListViewController.swift; sourceTree = "<group>"; };
B566C8EB24F9D694001134A1 /* Modern.PokedexDemo.ItemCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.ItemCell.swift; sourceTree = "<group>"; };
B566C8E724F9D406001134A1 /* Modern.PokedexDemo.UIKit.ListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.UIKit.ListView.swift; sourceTree = "<group>"; };
B566C8E924F9D412001134A1 /* Modern.PokedexDemo.UIKit.ListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.UIKit.ListViewController.swift; sourceTree = "<group>"; };
B566C8EB24F9D694001134A1 /* Modern.PokedexDemo.UIKit.ItemCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.UIKit.ItemCell.swift; sourceTree = "<group>"; };
B566C8ED24FA1EA3001134A1 /* Modern.PokedexDemo.Details.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.Details.swift; sourceTree = "<group>"; };
B5931B4125124756007DA58E /* Advanced.EvolutionDemo.V1.FromV2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.V1.FromV2.swift; sourceTree = "<group>"; };
B5931B432512480A007DA58E /* Advanced.EvolutionDemo.V2.FromV1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.V2.FromV1.swift; sourceTree = "<group>"; };
@@ -185,7 +177,7 @@
B5A3919F24E8F00A00E7E8BD /* Modern.ColorsDemo.UIKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.ColorsDemo.UIKit.swift; sourceTree = "<group>"; };
B5A391A124E8F01F00E7E8BD /* ⭐Modern.ColorsDemo.UIKit.ListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "⭐Modern.ColorsDemo.UIKit.ListViewController.swift"; sourceTree = "<group>"; };
B5A391A324E8F04300E7E8BD /* Modern.ColorsDemo.UIKit.ListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.ColorsDemo.UIKit.ListView.swift; sourceTree = "<group>"; };
B5A391A524E8F4EA00E7E8BD /* ⭐️Modern.ColorsDemo.MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "⭐️Modern.ColorsDemo.MainView.swift"; sourceTree = "<group>"; };
B5A391A524E8F4EA00E7E8BD /* Modern.ColorsDemo.MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.ColorsDemo.MainView.swift; sourceTree = "<group>"; };
B5A391A924E9104300E7E8BD /* Modern.ColorsDemo.UIKit.ItemCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.ColorsDemo.UIKit.ItemCell.swift; sourceTree = "<group>"; };
B5A391AB24E9143B00E7E8BD /* Modern.ColorsDemo.UIKit.DetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.ColorsDemo.UIKit.DetailView.swift; sourceTree = "<group>"; };
B5A391AD24E9150F00E7E8BD /* ⭐Modern.ColorsDemo.UIKit.DetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "⭐Modern.ColorsDemo.UIKit.DetailViewController.swift"; sourceTree = "<group>"; };
@@ -214,6 +206,7 @@
B5A5440A25049492000DC5E3 /* Advanced.EvolutionDemo.V3.Creature.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.V3.Creature.swift; sourceTree = "<group>"; };
B5A5440C2504949C000DC5E3 /* Advanced.EvolutionDemo.V4.Creature.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.V4.Creature.swift; sourceTree = "<group>"; };
B5C18F3225138700001BEFB3 /* Advanced.EvolutionDemo.ProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.ProgressView.swift; sourceTree = "<group>"; };
B5C795B525D8EE2B00BDACC1 /* Modern.PokedexDemo.UIKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modern.PokedexDemo.UIKit.swift; sourceTree = "<group>"; };
B5D6F1F7250E07FD00DF5D2F /* Advanced.EvolutionDemo.V1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.V1.swift; sourceTree = "<group>"; };
B5D6F1FB250E0B1700DF5D2F /* Advanced.EvolutionDemo.V2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.V2.swift; sourceTree = "<group>"; };
B5D6F1FD250E0B3F00DF5D2F /* Advanced.EvolutionDemo.GeologicalPeriod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Advanced.EvolutionDemo.GeologicalPeriod.swift; sourceTree = "<group>"; };
@@ -232,11 +225,8 @@
files = (
B5A3917724E6990700E7E8BD /* CoreLocation.framework in Frameworks */,
B5A3916B24E698F900E7E8BD /* CoreStore.framework in Frameworks */,
B5A3917124E698F900E7E8BD /* CoreStore.framework in Frameworks */,
B5A3917924E6991600E7E8BD /* SwiftUI.framework in Frameworks */,
B5A3917524E6990200E7E8BD /* MapKit.framework in Frameworks */,
B5A3916F24E698F900E7E8BD /* CoreStore.framework in Frameworks */,
B5A3916D24E698F900E7E8BD /* CoreStore.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -412,7 +402,7 @@
children = (
B5A3918E24E7E06500E7E8BD /* Modern.ColorsDemo.swift */,
B5A3919724E7E67000E7E8BD /* Modern.ColorsDemo.Filter.swift */,
B5A391A524E8F4EA00E7E8BD /* ⭐️Modern.ColorsDemo.MainView.swift */,
B5A391A524E8F4EA00E7E8BD /* Modern.ColorsDemo.MainView.swift */,
B5A3919C24E8EE9000E7E8BD /* ⭐UIKit */,
B5A3919B24E8EE8100E7E8BD /* ⭐SwiftUI */,
B5A3919024E7E0B000E7E8BD /* Models */,
@@ -458,9 +448,7 @@
B5A391B024E96AF600E7E8BD /* Modern.PokedexDemo.swift */,
B531EFEA24EB5ECD005F247D /* ⭐Modern.PokedexDemo.Service.swift */,
B531EFEC24EB7453005F247D /* Modern.PokedexDemo.MainView.swift */,
B566C8E724F9D406001134A1 /* Modern.PokedexDemo.ListView.swift */,
B566C8E924F9D412001134A1 /* Modern.PokedexDemo.ListViewController.swift */,
B566C8EB24F9D694001134A1 /* Modern.PokedexDemo.ItemCell.swift */,
B5C795B425D8EE1A00BDACC1 /* ⭐UIKit */,
B5A391B224E96B7400E7E8BD /* ⭐Models */,
);
path = "⭐PokedexDemo";
@@ -549,6 +537,17 @@
name = Models;
sourceTree = "<group>";
};
B5C795B425D8EE1A00BDACC1 /* ⭐UIKit */ = {
isa = PBXGroup;
children = (
B5C795B525D8EE2B00BDACC1 /* Modern.PokedexDemo.UIKit.swift */,
B566C8E724F9D406001134A1 /* Modern.PokedexDemo.UIKit.ListView.swift */,
B566C8E924F9D412001134A1 /* Modern.PokedexDemo.UIKit.ListViewController.swift */,
B566C8EB24F9D694001134A1 /* Modern.PokedexDemo.UIKit.ItemCell.swift */,
);
name = "⭐UIKit";
sourceTree = "<group>";
};
B5D6F1F9250E08D200DF5D2F /* V1 */ = {
isa = PBXGroup;
children = (
@@ -622,7 +621,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1160;
LastUpgradeCheck = 1200;
LastUpgradeCheck = 1300;
TargetAttributes = {
B5A3911824E5429200E7E8BD = {
CreatedOnToolsVersion = 11.6;
@@ -704,6 +703,7 @@
B5A543ED24FB84BE000DC5E3 /* Classic.ColorsDemo.MainView.swift in Sources */,
B5A543DD24FB78F9000DC5E3 /* Classic.ColorsDemo.Palette.swift in Sources */,
B5A3919824E7E67000E7E8BD /* Modern.ColorsDemo.Filter.swift in Sources */,
B5C795B625D8EE2B00BDACC1 /* Modern.PokedexDemo.UIKit.swift in Sources */,
B5A3919224E7E0C600E7E8BD /* Modern.ColorsDemo.Palette.swift in Sources */,
B5A3919E24E8EEB600E7E8BD /* Modern.ColorsDemo.SwiftUI.swift in Sources */,
B5A391A024E8F00A00E7E8BD /* Modern.ColorsDemo.UIKit.swift in Sources */,
@@ -711,16 +711,16 @@
B5A3916024E6925900E7E8BD /* Modern.PlacemarksDemo.MapView.swift in Sources */,
B5A3916524E698C700E7E8BD /* Modern.PlacemarksDemo.Place.swift in Sources */,
B566C8EE24FA1EA3001134A1 /* Modern.PokedexDemo.Details.swift in Sources */,
B566C8EC24F9D694001134A1 /* Modern.PokedexDemo.ItemCell.swift in Sources */,
B566C8E824F9D406001134A1 /* Modern.PokedexDemo.ListView.swift in Sources */,
B566C8EA24F9D412001134A1 /* Modern.PokedexDemo.ListViewController.swift in Sources */,
B566C8EC24F9D694001134A1 /* Modern.PokedexDemo.UIKit.ItemCell.swift in Sources */,
B566C8E824F9D406001134A1 /* Modern.PokedexDemo.UIKit.ListView.swift in Sources */,
B566C8EA24F9D412001134A1 /* Modern.PokedexDemo.UIKit.ListViewController.swift in Sources */,
B531EFED24EB7453005F247D /* Modern.PokedexDemo.MainView.swift in Sources */,
B5A3918C24E7B44B00E7E8BD /* Modern.TimeZonesDemo.ItemView.swift in Sources */,
B5A3918A24E7AD1800E7E8BD /* Modern.TimeZonesDemo.ListView.swift in Sources */,
B5A3918624E7A54A00E7E8BD /* Modern.TimeZonesDemo.TimeZone.swift in Sources */,
B5A543EB24FB84AF000DC5E3 /* ⭐Classic.ColorsDemo.DetailViewController.swift in Sources */,
B5A543F124FB84DD000DC5E3 /* ⭐Classic.ColorsDemo.ListViewController.swift in Sources */,
B5A391A624E8F4EA00E7E8BD /* ⭐️Modern.ColorsDemo.MainView.swift in Sources */,
B5A391A624E8F4EA00E7E8BD /* Modern.ColorsDemo.MainView.swift in Sources */,
B5A3916224E697BA00E7E8BD /* ⭐Modern.PlacemarksDemo.MainView.swift in Sources */,
B5A391B424E96C0A00E7E8BD /* ⭐Modern.PokedexDemo.Form.swift in Sources */,
B531EFE924EB5A53005F247D /* ⭐Modern.PokedexDemo.PokedexEntry.swift in Sources */,
@@ -797,6 +797,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
ONLY_ACTIVE_ARCH = YES;
};
name = Debug;
};

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1200"
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"

View File

@@ -20,8 +20,8 @@ struct InstructionsView: View {
var body: some View {
ZStack(alignment: .center) {
Color.white
.cornerRadius(10)
RoundedRectangle(cornerRadius: 10, style: .continuous)
.fill(Color.white)
.shadow(color: Color(.sRGB, white: 0.5, opacity: 0.3), radius: 2, x: 1, y: 1)
VStack(alignment: .leading, spacing: 3) {
ForEach(self.rows, id: \.header) { row in

View File

@@ -73,7 +73,9 @@ extension Menu {
title: "Pokedex API",
subtitle: "Importing JSON data from external source",
destination: {
Modern.PokedexDemo.MainView()
Modern.PokedexDemo.MainView(
listView: Modern.PokedexDemo.UIKit.ListView.init
)
}
)
}

View File

@@ -45,17 +45,16 @@ extension Advanced.EvolutionDemo {
.padding(.horizontal)
GeometryReader { geometry in
ZStack(alignment: .leading) {
Color.gray
.opacity(0.2)
RoundedRectangle(cornerRadius: 4, style: .continuous)
.fill(Color.gray.opacity(0.2))
.frame(width: geometry.size.width, height: 8)
.cornerRadius(4.0)
Color.blue
RoundedRectangle(cornerRadius: 4, style: .continuous)
.fill(Color.blue)
.frame(
width: geometry.size.width
* self.progressObserver.fractionCompleted,
height: 8
)
.cornerRadius(4.0)
}
}
.fixedSize(horizontal: false, vertical: true)

View File

@@ -1,12 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="16119" systemVersion="19F101" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="17709" systemVersion="20C5048l" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Palette" representedClassName="Classic_ColorsDemo_Palette" syncable="YES">
<attribute name="brightness" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="colorGroup" optional="YES" transient="YES" attributeType="String"/>
<attribute name="hue" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="saturation" attributeType="Float" defaultValueString="0.0" usesScalarValueType="YES"/>
<fetchedProperty name="testFetchProperty" optional="YES">
<fetchRequest name="fetchedPropertyFetchRequest" entity="Palette"/>
</fetchedProperty>
</entity>
<elements>
<element name="Palette" positionX="-63" positionY="-18" width="128" height="103"/>
<element name="Palette" positionX="-63" positionY="-18" width="128" height="110"/>
</elements>
</model>

View File

@@ -13,12 +13,6 @@ extension Modern.ColorsDemo {
struct MainView<ListView: View, DetailView: View>: View {
/**
Sample 1: Setting a sectioned `ListPublisher` declared as an `@ObservedObject`
*/
@ObservedObject
private var listPublisher: ListPublisher<Modern.ColorsDemo.Palette>
// MARK: Internal
init(
@@ -30,38 +24,24 @@ extension Modern.ColorsDemo {
self.listView = listView
self.detailView = detailView
self.listPublisher = Modern.ColorsDemo.palettesPublisher
self._filter = Binding(
get: { Modern.ColorsDemo.filter },
set: { Modern.ColorsDemo.filter = $0 }
)
}
// MARK: View
var body: some View {
let detailView: AnyView
if let selectedPalette = self.selectedPalette {
detailView = AnyView(
self.detailView(selectedPalette)
)
}
else {
detailView = AnyView(EmptyView())
}
let listPublisher = self.listPublisher
return VStack(spacing: 0) {
self.listView(listPublisher, { self.selectedPalette = $0 })
self.listView(self.$palettes, { self.selectedPalette = $0 })
.navigationBarTitle(
Text("Colors (\(listPublisher.snapshot.numberOfItems) objects)")
Text("Colors (\(self.palettes.count) objects)")
)
.frame(minHeight: 0, maxHeight: .infinity)
detailView
.edgesIgnoringSafeArea(.all)
.frame(minHeight: 0, maxHeight: .infinity)
self.selectedPalette.map {
self.detailView($0)
.edgesIgnoringSafeArea(.all)
.frame(minHeight: 0, maxHeight: .infinity)
}
}
.navigationBarItems(
leading: HStack {
@@ -91,6 +71,9 @@ extension Modern.ColorsDemo {
// MARK: Private
@ListState(Modern.ColorsDemo.palettesPublisher)
private var palettes: ListSnapshot
private let listView: (
_ listPublisher: ListPublisher<Modern.ColorsDemo.Palette>,
_ onPaletteTapped: @escaping (ObjectPublisher<Modern.ColorsDemo.Palette>) -> Void
@@ -103,12 +86,13 @@ extension Modern.ColorsDemo {
@State
private var selectedPalette: ObjectPublisher<Modern.ColorsDemo.Palette>?
@Binding
private var filter: Modern.ColorsDemo.Filter
@State
private var filter: Modern.ColorsDemo.Filter = Modern.ColorsDemo.filter
private func changeFilter() {
Modern.ColorsDemo.filter = Modern.ColorsDemo.filter.next()
self.filter = Modern.ColorsDemo.filter
}
private func clearColors() {
@@ -118,6 +102,7 @@ extension Modern.ColorsDemo {
try transaction.deleteAll(From<Modern.ColorsDemo.Palette>())
},
sourceIdentifier: TransactionSource.clear,
completion: { _ in }
)
}
@@ -129,6 +114,7 @@ extension Modern.ColorsDemo {
_ = transaction.create(Into<Modern.ColorsDemo.Palette>())
},
sourceIdentifier: TransactionSource.add,
completion: { _ in }
)
}
@@ -143,6 +129,7 @@ extension Modern.ColorsDemo {
palette.setRandomHue()
}
},
sourceIdentifier: TransactionSource.shuffle,
completion: { _ in }
)
}

View File

@@ -30,14 +30,19 @@ extension Modern.ColorsDemo.UIKit {
return UIViewControllerType(self.palette)
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Self.Context) {}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Self.Context) {
uiViewController.palette = Modern.ColorsDemo.dataStack.monitorObject(
self.palette.object!
)
}
static func dismantleUIViewController(_ uiViewController: UIViewControllerType, coordinator: Void) {}
// MARK: Private
private let palette: ObjectPublisher<Modern.ColorsDemo.Palette>
private var palette: ObjectPublisher<Modern.ColorsDemo.Palette>
}
}

View File

@@ -2,6 +2,7 @@
// Demo
// Copyright © 2020 John Rommel Estropia, Inc. All rights reserved.
import SwiftUI
import CoreStore
// MARK: - Modern
@@ -45,7 +46,10 @@ extension Modern {
static let palettesPublisher: ListPublisher<Modern.ColorsDemo.Palette> = Modern.ColorsDemo.dataStack.publishList(
From<Modern.ColorsDemo.Palette>()
.sectionBy(\.$colorGroup)
.sectionBy(
\.$colorGroup,
sectionIndexTransformer: { $0?.first?.uppercased() }
)
.where(Modern.ColorsDemo.filter.whereClause())
.orderBy(.ascending(\.$hue))
)
@@ -56,11 +60,27 @@ extension Modern {
try! Modern.ColorsDemo.palettesPublisher.refetch(
From<Modern.ColorsDemo.Palette>()
.sectionBy(\.$colorGroup)
.sectionBy(
\.$colorGroup,
sectionIndexTransformer: { $0?.first?.uppercased() }
)
.where(self.filter.whereClause())
.orderBy(.ascending(\.$hue))
.orderBy(.ascending(\.$hue)),
sourceIdentifier: TransactionSource.refetch
)
}
}
// MARK: - TransactionSource
enum TransactionSource {
case add
case delete
case shuffle
case clear
case refetch
}
}
}

View File

@@ -15,10 +15,10 @@ extension Modern.ColorsDemo.SwiftUI {
struct DetailView: View {
/**
Sample 1: Setting an `ObjectPublisher` declared as an `@ObservedObject`
Sample 1: Using a `ObjectState` to observe object changes. Note that the `ObjectSnapshot` is always `Optional`
*/
@ObservedObject
private var palette: ObjectPublisher<Modern.ColorsDemo.Palette>
@ObjectState
private var palette: ObjectSnapshot<Modern.ColorsDemo.Palette>?
/**
Sample 2: Setting properties that can be binded to controls (`Slider` in this case) by creating custom `@Binding` instances that updates the store when the values change.
@@ -34,7 +34,7 @@ extension Modern.ColorsDemo.SwiftUI {
init(_ palette: ObjectPublisher<Modern.ColorsDemo.Palette>) {
self.palette = palette
self._palette = .init(palette)
self._hue = Binding(
get: { palette.hue ?? 0 },
set: { percentage in
@@ -84,56 +84,50 @@ extension Modern.ColorsDemo.SwiftUI {
var body: some View {
guard let snapshot = self.palette.snapshot else {
if let palette = self.palette {
return AnyView(EmptyView())
}
return AnyView(
GeometryReader { geometry in
ZStack(alignment: .bottom) {
Color(snapshot.$color)
ZStack {
Color.white
.cornerRadius(10)
.shadow(color: Color(.sRGB, white: 0.5, opacity: 0.3), radius: 2, x: 1, y: 1)
VStack(alignment: .leading, spacing: 10) {
HStack {
Text("H: \(Int(snapshot.$hue * 359))°")
.frame(width: 80)
Slider(
value: self.$hue,
in: 0 ... 1,
step: 1 / 359
)
}
HStack {
Text("S: \(Int(snapshot.$saturation * 100))%")
.frame(width: 80)
Slider(
value: self.$saturation,
in: 0 ... 1,
step: 1 / 100
)
}
HStack {
Text("B: \(Int(snapshot.$brightness * 100))%")
.frame(width: 80)
Slider(
value: self.$brightness,
in: 0 ... 1,
step: 1 / 100
)
}
ZStack(alignment: .center) {
Color(palette.$color)
ZStack {
RoundedRectangle(cornerRadius: 10, style: .continuous)
.fill(Color.white)
.shadow(color: Color(.sRGB, white: 0.5, opacity: 0.3), radius: 2, x: 1, y: 1)
VStack(alignment: .leading, spacing: 10) {
HStack {
Text("H: \(Int(palette.$hue * 359))°")
.frame(width: 80)
Slider(
value: self.$hue,
in: 0 ... 1,
step: 1 / 359
)
}
HStack {
Text("S: \(Int(palette.$saturation * 100))%")
.frame(width: 80)
Slider(
value: self.$saturation,
in: 0 ... 1,
step: 1 / 100
)
}
HStack {
Text("B: \(Int(palette.$brightness * 100))%")
.frame(width: 80)
Slider(
value: self.$brightness,
in: 0 ... 1,
step: 1 / 100
)
}
.foregroundColor(Color(.sRGB, white: 0, opacity: 0.8))
.padding()
}
.fixedSize(horizontal: false, vertical: true)
.foregroundColor(Color(.sRGB, white: 0, opacity: 0.8))
.padding()
.padding(geometry.safeAreaInsets)
}
.fixedSize(horizontal: false, vertical: true)
.padding()
}
)
}
}
}
}

View File

@@ -14,36 +14,34 @@ extension Modern.ColorsDemo.SwiftUI {
struct ItemView: View {
/**
Sample 1: Setting an `ObjectPublisher` declared as an `@ObservedObject`
Sample 1: Using a `ObjectState` to observe object changes. Note that the `ObjectSnapshot` is always `Optional`
*/
@ObservedObject
private var palette: ObjectPublisher<Modern.ColorsDemo.Palette>
// MARK: Internal
@ObjectState
private var palette: ObjectSnapshot<Modern.ColorsDemo.Palette>?
/**
Sample 2: Initializing a `ObjectState` from an existing `ObjectPublisher`
*/
internal init(_ palette: ObjectPublisher<Modern.ColorsDemo.Palette>) {
self.palette = palette
self._palette = .init(palette)
}
// MARK: View
/**
Sample 3: Readding values directly from the `ObjectSnapshot`
*/
var body: some View {
guard let palette = self.palette.snapshot else {
if let palette = self.palette {
return AnyView(EmptyView())
}
return AnyView(
Color(palette.$color).overlay(
Text(palette.$colorText)
.foregroundColor(palette.$brightness > 0.6 ? .black : .white)
.padding(),
alignment: .leading
)
)
.animation(.default)
}
}
}
}

View File

@@ -5,7 +5,6 @@
import CoreStore
import SwiftUI
// MARK: - Modern.ColorsDemo.SwiftUI
extension Modern.ColorsDemo.SwiftUI {
@@ -15,53 +14,58 @@ extension Modern.ColorsDemo.SwiftUI {
struct ListView: View {
/**
Sample 1: Setting a sectioned `ListPublisher` declared as an `@ObservedObject`
Sample 1: Using a `ListState` to observe list changes
*/
@ObservedObject
private var listPublisher: ListPublisher<Modern.ColorsDemo.Palette>
@ListState
private var palettes: ListSnapshot<Modern.ColorsDemo.Palette>
/**
Sample 2: Assigning sections and items of the `ListPublisher` to corresponding `View`s
Sample 2: Initializing a `ListState` from an existing `ListPublisher`
*/
var body: some View {
let listSnapshot = self.listPublisher.snapshot
return List {
ForEach(listSnapshot.sectionIDs, id: \.self) { (sectionID) in
Section(header: Text(sectionID)) {
ForEach(listSnapshot.items(inSectionWithID: sectionID), id: \.self) { palette in
init(
listPublisher: ListPublisher<Modern.ColorsDemo.Palette>,
onPaletteTapped: @escaping (ObjectPublisher<Modern.ColorsDemo.Palette>) -> Void
) {
self._palettes = .init(listPublisher)
self.onPaletteTapped = onPaletteTapped
}
/**
Sample 3: Assigning sections and items of the `ListSnapshot` to corresponding `View`s by using the correct `ForEach` overloads.
*/
var body: some View {
List {
ForEach(sectionIn: self.palettes) { section in
Section(header: Text(section.sectionID)) {
ForEach(objectIn: section) { palette in
Button(
action: {
self.onPaletteTapped(palette)
},
label: {
Modern.ColorsDemo.SwiftUI.ItemView(palette)
}
)
.listRowInsets(.init())
}
.onDelete { itemIndices in
self.deleteColors(at: itemIndices, in: sectionID)
self.deleteColors(at: itemIndices, in: section.sectionID)
}
}
}
GeometryReader { geometry in
Spacer(minLength: geometry.safeAreaInsets.bottom)
}
}
.animation(.default)
.listStyle(PlainListStyle())
}
// MARK: Internal
init(
listPublisher: ListPublisher<Modern.ColorsDemo.Palette>,
onPaletteTapped: @escaping (ObjectPublisher<Modern.ColorsDemo.Palette>) -> Void
) {
self.listPublisher = listPublisher
self.onPaletteTapped = onPaletteTapped
.edgesIgnoringSafeArea([])
}
@@ -71,7 +75,7 @@ extension Modern.ColorsDemo.SwiftUI {
private func deleteColors(at indices: IndexSet, in sectionID: String) {
let objectIDsToDelete = self.listPublisher.snapshot.itemIDs(
let objectIDsToDelete = self.palettes.itemIDs(
inSectionWithID: sectionID,
atIndices: indices
)

View File

@@ -40,6 +40,15 @@ extension Modern.ColorsDemo.UIKit {
/**
Sample 3: We can end monitoring updates anytime. `removeObserver()` was called here for illustration purposes only. `ObjectMonitor`s safely remove deallocated observers automatically.
*/
var palette: ObjectMonitor<Modern.ColorsDemo.Palette> {
didSet {
oldValue.removeObserver(self)
self.startMonitoringObject()
}
}
deinit {
self.palette.removeObserver(self)
@@ -82,7 +91,8 @@ extension Modern.ColorsDemo.UIKit {
func objectMonitor(
_ monitor: ObjectMonitor<Modern.ColorsDemo.Palette>,
didUpdateObject object: Modern.ColorsDemo.Palette,
changedPersistentKeys: Set<KeyPathString>
changedPersistentKeys: Set<KeyPathString>,
sourceIdentifier: Any?
) {
self.reloadPaletteInfo(object, changedKeys: changedPersistentKeys)
@@ -183,9 +193,8 @@ extension Modern.ColorsDemo.UIKit {
equalTo: view.safeAreaLayoutGuide.leadingAnchor,
constant: 10
),
containerView.bottomAnchor.constraint(
equalTo: view.safeAreaLayoutGuide.bottomAnchor,
constant: -10
containerView.centerYAnchor.constraint(
equalTo: view.safeAreaLayoutGuide.centerYAnchor
),
containerView.trailingAnchor.constraint(
equalTo: view.safeAreaLayoutGuide.trailingAnchor,
@@ -223,8 +232,6 @@ extension Modern.ColorsDemo.UIKit {
// MARK: Private
private let palette: ObjectMonitor<Modern.ColorsDemo.Palette>
@available(*, unavailable)
required init?(coder: NSCoder) {

View File

@@ -15,9 +15,9 @@ extension Modern.ColorsDemo.UIKit {
final class ListViewController: UITableViewController {
/**
Sample 1: Setting up a `DiffableDataSource.TableViewAdapter` that will manage tableView snapshot updates automatically. We can use the built-in `DiffableDataSource.TableViewAdapter` type directly, but in our case we want to enabled `UITableView` cell deletions so we create a custom subclass `DeletionEnabledDataSource` (see declaration below).
Sample 1: Setting up a `DiffableDataSource.TableViewAdapter` that will manage tableView snapshot updates automatically. We can use the built-in `DiffableDataSource.TableViewAdapter` type directly, but in our case we want to enabled `UITableView` cell deletions so we create a custom subclass `CustomDataSource` (see declaration below).
*/
private lazy var dataSource: DiffableDataSource.TableViewAdapter<Modern.ColorsDemo.Palette> = DeletionEnabledDataSource(
private lazy var dataSource: DiffableDataSource.TableViewAdapter<Modern.ColorsDemo.Palette> = CustomDataSource(
tableView: self.tableView,
dataStack: Modern.ColorsDemo.dataStack,
cellProvider: { (tableView, indexPath, palette) in
@@ -32,21 +32,26 @@ extension Modern.ColorsDemo.UIKit {
)
/**
Sample 2: Once the views are created, we can start binding `ListPublisher` updates to the `DiffableDataSource`. We typically call this at the end of `viewDidLoad`. Note that the `addObserver`'s closure argument will only be called on the succeeding updates, so to immediately display the current values, we need to call `dataSource.apply()` once.
Sample 2: Once the views are created, we can start binding `ListPublisher` updates to the `DiffableDataSource`. We typically call this at the end of `viewDidLoad`. Note that the `addObserver`'s closure argument will only be called on the succeeding updates, so to immediately display the current values, we need to call `dataSource.apply()` once. This example inspects the optional `transactionSource` to determine the source of the update which is helpful for debugging or for fine-tuning animations.
*/
private func startObservingList() {
self.listPublisher.addObserver(self) { (listPublisher) in
let dataSource = self.dataSource
self.listPublisher.addObserver(self, notifyInitial: true) { (listPublisher, transactionSource) in
self.dataSource.apply(
listPublisher.snapshot,
animatingDifferences: true
)
switch transactionSource as? Modern.ColorsDemo.TransactionSource {
case .add,
.delete,
.shuffle,
.clear:
dataSource.apply(listPublisher.snapshot, animatingDifferences: true)
case nil,
.refetch:
dataSource.apply(listPublisher.snapshot, animatingDifferences: false)
}
}
self.dataSource.apply(
listPublisher.snapshot,
animatingDifferences: false
)
}
/**
@@ -58,9 +63,11 @@ extension Modern.ColorsDemo.UIKit {
}
/**
Sample 4: This is the custom `DiffableDataSource.TableViewAdapter` subclass we wrote that enabled swipe-to-delete gestures on the `UITableView`.
Sample 4: This is the custom `DiffableDataSource.TableViewAdapter` subclass we wrote that enabled swipe-to-delete gestures and section index titles on the `UITableView`.
*/
final class DeletionEnabledDataSource: DiffableDataSource.TableViewAdapter<Modern.ColorsDemo.Palette> {
final class CustomDataSource: DiffableDataSource.TableViewAdapter<Modern.ColorsDemo.Palette> {
// MARK: UITableViewDataSource
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
@@ -76,6 +83,7 @@ extension Modern.ColorsDemo.UIKit {
transaction.delete(objectIDs: [itemID])
},
sourceIdentifier: Modern.ColorsDemo.TransactionSource.delete,
completion: { _ in }
)
@@ -83,6 +91,16 @@ extension Modern.ColorsDemo.UIKit {
break
}
}
override func sectionIndexTitles(for tableView: UITableView) -> [String]? {
return self.sectionIndexTitlesForAllSections().compactMap({ $0 })
}
override func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
return index
}
}

View File

@@ -25,7 +25,7 @@ extension Modern.PlacemarksDemo {
Modern.PlacemarksDemo.dataStack.perform(
asynchronous: { (transaction) in
let place = self.place.asEditable(in: transaction)
let place = self.$place?.asEditable(in: transaction)
place?.annotation = .init(coordinate: coordinate)
},
completion: { _ in }
@@ -42,7 +42,7 @@ extension Modern.PlacemarksDemo {
_ = try? Modern.PlacemarksDemo.dataStack.perform(
synchronous: { (transaction) in
let place = self.place.asEditable(in: transaction)
let place = self.$place?.asEditable(in: transaction)
place?.setRandomLocation()
}
)
@@ -71,22 +71,25 @@ extension Modern.PlacemarksDemo {
// MARK: Internal
@ObservedObject
var place: ObjectPublisher<Modern.PlacemarksDemo.Place>
@ObjectState(Modern.PlacemarksDemo.placePublisher)
var place: ObjectSnapshot<Modern.PlacemarksDemo.Place>?
init() {
self.place = Modern.PlacemarksDemo.placePublisher
self.sinkCancellable = self.place.sink(
self.sinkCancellable = self.$place?.reactive.snapshot().sink(
receiveCompletion: { _ in
// Deleted, do nothing
},
receiveValue: { [self] (snapshot) in
guard let snapshot = snapshot else {
return
}
self.geocoder.geocode(place: snapshot) { (title, subtitle) in
guard self.place.snapshot == snapshot else {
guard self.place == snapshot else {
return
}
@@ -104,22 +107,29 @@ extension Modern.PlacemarksDemo {
// MARK: View
var body: some View {
Modern.PlacemarksDemo.MapView(
place: self.place.snapshot,
onTap: { coordinate in
Group {
if let place = self.place {
self.demoAsynchronousTransaction(coordinate: coordinate)
Modern.PlacemarksDemo.MapView(
place: place,
onTap: { coordinate in
self.demoAsynchronousTransaction(coordinate: coordinate)
}
)
.overlay(
InstructionsView(
("Random", "Sets random coordinate"),
("Tap", "Sets to tapped coordinate")
)
.padding(.leading, 10)
.padding(.bottom, 40),
alignment: .bottomLeading
)
}
)
.overlay(
InstructionsView(
("Random", "Sets random coordinate"),
("Tap", "Sets to tapped coordinate")
)
.padding(.leading, 10)
.padding(.bottom, 40),
alignment: .bottomLeading
)
}
.navigationBarTitle("Placemarks")
.navigationBarItems(
trailing: Button("Random") {
@@ -132,7 +142,7 @@ extension Modern.PlacemarksDemo {
// MARK: Private
private var sinkCancellable: AnyCancellable? = nil
private var sinkCancellable: AnyCancellable?
private let geocoder = Modern.PlacemarksDemo.Geocoder()
}
}

View File

@@ -12,30 +12,28 @@ extension Modern.PokedexDemo {
// MARK: - Modern.PokedexDemo.MainView
struct MainView: View {
struct MainView<ListView: View>: View {
// MARK: Internal
init() {
self.pokedexEntries = Modern.PokedexDemo.pokedexEntries
init(
listView: @escaping () -> ListView
) {
self.listView = listView
}
// MARK: View
var body: some View {
let pokedexEntries = self.pokedexEntries.snapshot
return ZStack {
ZStack {
Modern.PokedexDemo.ListView(
service: self.service,
listPublisher: self.pokedexEntries
)
self.listView()
.frame(minHeight: 0, maxHeight: .infinity)
.edgesIgnoringSafeArea(.vertical)
if pokedexEntries.isEmpty {
if self.pokedexEntries.isEmpty {
VStack(alignment: .center, spacing: 30) {
Text("This demo needs to make a network connection to download Pokedex entries")
@@ -64,11 +62,17 @@ extension Modern.PokedexDemo {
// MARK: Private
@ObservedObject
private var pokedexEntries: ListPublisher<Modern.PokedexDemo.PokedexEntry>
@ListState(
From<Modern.PokedexDemo.PokedexEntry>()
.orderBy(.ascending(\.$index)),
in: Modern.PokedexDemo.dataStack
)
private var pokedexEntries
@ObservedObject
private var service: Modern.PokedexDemo.Service = .init()
private let listView: () -> ListView
}
}
@@ -82,7 +86,9 @@ struct _Demo_Modern_PokedexDemo_MainView_Preview: PreviewProvider {
static var previews: some View {
Modern.PokedexDemo.MainView()
Modern.PokedexDemo.MainView(
listView: Modern.PokedexDemo.UIKit.ListView.init
)
}
}

View File

@@ -7,9 +7,9 @@ import CoreStore
import UIKit
// MARK: - Modern.PokedexDemo
// MARK: - Modern.PokedexDemo.UIKit
extension Modern.PokedexDemo {
extension Modern.PokedexDemo.UIKit {
// MARK: - Modern.PokedexDemo.ItemCell
@@ -17,7 +17,7 @@ extension Modern.PokedexDemo {
// MARK: Internal
static let reuseIdentifier: String = NSStringFromClass(Modern.PokedexDemo.ItemCell.self)
static let reuseIdentifier: String = NSStringFromClass(Modern.PokedexDemo.UIKit.ItemCell.self)
func setPokedexEntry(
_ pokedexEntry: Modern.PokedexDemo.PokedexEntry,
@@ -61,6 +61,7 @@ extension Modern.PokedexDemo {
contentView.backgroundColor = UIColor.placeholderText.withAlphaComponent(0.1)
contentView.layer.cornerRadius = 10
contentView.layer.cornerCurve = .continuous
contentView.layer.masksToBounds = true
}

View File

@@ -5,9 +5,9 @@
import CoreStore
import SwiftUI
// MARK: - Modern.PokedexDemo
// MARK: - Modern.PokedexDemo.UIKit
extension Modern.PokedexDemo {
extension Modern.PokedexDemo.UIKit {
// MARK: - Modern.PokedexDemo.ListView
@@ -15,19 +15,20 @@ extension Modern.PokedexDemo {
// MARK: Internal
init(
service: Modern.PokedexDemo.Service,
listPublisher: ListPublisher<Modern.PokedexDemo.PokedexEntry>
) {
init() {
self.service = service
self.listPublisher = listPublisher
self.service = Modern.PokedexDemo.Service.init()
self.listPublisher = Modern.PokedexDemo.dataStack
.publishList(
From<Modern.PokedexDemo.PokedexEntry>()
.orderBy(.ascending(\.$index))
)
}
// MARK: UIViewControllerRepresentable
typealias UIViewControllerType = Modern.PokedexDemo.ListViewController
typealias UIViewControllerType = Modern.PokedexDemo.UIKit.ListViewController
func makeUIViewController(context: Self.Context) -> UIViewControllerType {
@@ -53,7 +54,7 @@ extension Modern.PokedexDemo {
#if DEBUG
struct _Demo_Modern_PokedexDemo_ListView_Preview: PreviewProvider {
struct _Demo_Modern_PokedexDemo_UIKit_ListView_Preview: PreviewProvider {
// MARK: PreviewProvider
@@ -62,10 +63,7 @@ struct _Demo_Modern_PokedexDemo_ListView_Preview: PreviewProvider {
let service = Modern.PokedexDemo.Service()
service.fetchPokedexEntries()
return Modern.PokedexDemo.ListView(
service: service,
listPublisher: Modern.PokedexDemo.pokedexEntries
)
return Modern.PokedexDemo.UIKit.ListView()
}
}

View File

@@ -6,9 +6,9 @@ import CoreStore
import UIKit
// MARK: - Modern.PokedexDemo
// MARK: - Modern.PokedexDemo.UIKit
extension Modern.PokedexDemo {
extension Modern.PokedexDemo.UIKit {
// MARK: - Modern.PokedexDemo.ListViewController
@@ -65,8 +65,8 @@ extension Modern.PokedexDemo {
self.collectionView.backgroundColor = UIColor.systemBackground
self.collectionView.register(
Modern.PokedexDemo.ItemCell.self,
forCellWithReuseIdentifier: Modern.PokedexDemo.ItemCell.reuseIdentifier
Modern.PokedexDemo.UIKit.ItemCell.self,
forCellWithReuseIdentifier: Modern.PokedexDemo.UIKit.ItemCell.reuseIdentifier
)
self.startObservingList()
@@ -84,9 +84,9 @@ extension Modern.PokedexDemo {
cellProvider: { (collectionView, indexPath, pokedexEntry) in
let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: Modern.PokedexDemo.ItemCell.reuseIdentifier,
withReuseIdentifier: Modern.PokedexDemo.UIKit.ItemCell.reuseIdentifier,
for: indexPath
) as! Modern.PokedexDemo.ItemCell
) as! Modern.PokedexDemo.UIKit.ItemCell
cell.setPokedexEntry(pokedexEntry, service: self.service)
return cell
}

View File

@@ -0,0 +1,13 @@
//
// Demo
// Copyright © 2020 John Rommel Estropia, Inc. All rights reserved.
// MARK: - Modern.PokedexDemo
extension Modern.PokedexDemo {
// MARK: - UIKit
enum UIKit {}
}

View File

@@ -1,597 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
B50132242344E24300FC238B /* SwiftUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132232344E24300FC238B /* SwiftUIView.swift */; };
B50132282344E5E900FC238B /* SwiftUIContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B50132272344E5E900FC238B /* SwiftUIContainerViewController.swift */; };
B501323523477D2300FC238B /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B501323423477D2300FC238B /* SwiftUI.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
B503FADF1AFDC71700F90881 /* ListObserverDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADB1AFDC71700F90881 /* ListObserverDemoViewController.swift */; };
B503FAE01AFDC71700F90881 /* ObjectObserverDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADC1AFDC71700F90881 /* ObjectObserverDemoViewController.swift */; };
B503FAE11AFDC71700F90881 /* Palette.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADD1AFDC71700F90881 /* Palette.swift */; };
B503FAE21AFDC71700F90881 /* PaletteTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B503FADE1AFDC71700F90881 /* PaletteTableViewCell.swift */; };
B5125C121B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = B5125C111B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel */; };
B52977D91B120B80003D50A5 /* ObserversViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52977D81B120B80003D50A5 /* ObserversViewController.swift */; };
B52977DD1B120F3B003D50A5 /* TransactionsDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52977DC1B120F3B003D50A5 /* TransactionsDemoViewController.swift */; };
B52977DF1B120F83003D50A5 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B52977DE1B120F83003D50A5 /* MapKit.framework */; };
B52977E11B120F8A003D50A5 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B52977E01B120F8A003D50A5 /* CoreLocation.framework */; };
B52977E41B121635003D50A5 /* Place.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52977E31B121635003D50A5 /* Place.swift */; };
B54AAD4F1AF4D26E00848AE0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54AAD4E1AF4D26E00848AE0 /* AppDelegate.swift */; };
B54AAD521AF4D26E00848AE0 /* LegacyDemo.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B54AAD501AF4D26E00848AE0 /* LegacyDemo.xcdatamodeld */; };
B54AAD591AF4D26E00848AE0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD571AF4D26E00848AE0 /* Main.storyboard */; };
B54AAD5B1AF4D26E00848AE0 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */; };
B54AAD5E1AF4D26E00848AE0 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = B54AAD5C1AF4D26E00848AE0 /* LaunchScreen.xib */; };
B560070F1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = B560070E1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift */; };
B5635D192357F9F700B80E6B /* CollectionViewDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5635D182357F9F700B80E6B /* CollectionViewDemoViewController.swift */; };
B5635D1B2357FA4B00B80E6B /* PaletteCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5635D1A2357FA4B00B80E6B /* PaletteCollectionViewCell.swift */; };
B566E32A1B117B1F00F4F0C6 /* StackSetupDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566E3291B117B1F00F4F0C6 /* StackSetupDemoViewController.swift */; };
B566E3321B11DF3200F4F0C6 /* UserAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = B566E3311B11DF3200F4F0C6 /* UserAccount.swift */; };
B56964C91B20AC780075EE4A /* CustomLoggerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56964C81B20AC780075EE4A /* CustomLoggerViewController.swift */; };
B56964D71B231AE90075EE4A /* StackSetupDemo.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B56964D51B231AE90075EE4A /* StackSetupDemo.xcdatamodeld */; };
B56964DA1B231BCA0075EE4A /* MaleAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56964D91B231BCA0075EE4A /* MaleAccount.swift */; };
B56964DC1B231BCB0075EE4A /* FemaleAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56964DB1B231BCB0075EE4A /* FemaleAccount.swift */; };
B569650C1B2B36E10075EE4A /* FetchingAndQueryingDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B569650B1B2B36E10075EE4A /* FetchingAndQueryingDemoViewController.swift */; };
B56965181B2E20CC0075EE4A /* TimeZone.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56965171B2E20CC0075EE4A /* TimeZone.swift */; };
B569651A1B30888A0075EE4A /* FetchingResultsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56965191B30888A0075EE4A /* FetchingResultsViewController.swift */; };
B569651C1B30889A0075EE4A /* QueryingResultsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B569651B1B30889A0075EE4A /* QueryingResultsViewController.swift */; };
B56965291B3582D30075EE4A /* MigrationDemo.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = B56965271B3582D30075EE4A /* MigrationDemo.xcdatamodeld */; };
B5AA37EF2357D30300FFD4B9 /* ColorsDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5AA37EE2357D30300FFD4B9 /* ColorsDemo.swift */; };
B5C37EE52357FEBE0035A20D /* PaletteCollectionSectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C37EE42357FEBE0035A20D /* PaletteCollectionSectionHeaderView.swift */; };
B5E599321B5240F50084BD5F /* OrganismTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E599311B5240F50084BD5F /* OrganismTableViewCell.swift */; };
B5E89AD01C5292A2003B04A9 /* CoreStore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5BDC9211C202429008147CD /* CoreStore.framework */; };
B5E89AD11C5292A2003B04A9 /* CoreStore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B5BDC9211C202429008147CD /* CoreStore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B5EE25851B36E23C0000406B /* OrganismV1.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE25841B36E23C0000406B /* OrganismV1.swift */; };
B5EE25871B36E2520000406B /* OrganismV2.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE25861B36E2520000406B /* OrganismV2.swift */; };
B5EE258C1B36E40D0000406B /* MigrationsDemoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE258B1B36E40D0000406B /* MigrationsDemoViewController.swift */; };
B5EE259B1B3EA4890000406B /* OrganismV3.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE259A1B3EA4890000406B /* OrganismV3.swift */; };
B5EE259E1B3EC1B20000406B /* OrganismProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EE259D1B3EC1B20000406B /* OrganismProtocol.swift */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
B5E89ACF1C52929C003B04A9 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
B5E89AD11C5292A2003B04A9 /* CoreStore.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
B50132232344E24300FC238B /* SwiftUIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIView.swift; sourceTree = "<group>"; };
B50132272344E5E900FC238B /* SwiftUIContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIContainerViewController.swift; sourceTree = "<group>"; };
B501323423477D2300FC238B /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
B503FADB1AFDC71700F90881 /* ListObserverDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListObserverDemoViewController.swift; sourceTree = "<group>"; };
B503FADC1AFDC71700F90881 /* ObjectObserverDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjectObserverDemoViewController.swift; sourceTree = "<group>"; };
B503FADD1AFDC71700F90881 /* Palette.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Palette.swift; sourceTree = "<group>"; };
B503FADE1AFDC71700F90881 /* PaletteTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaletteTableViewCell.swift; sourceTree = "<group>"; };
B5125C111B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = OrganismV2ToV3.xcmappingmodel; sourceTree = "<group>"; };
B5125C131B521BA7003A42C7 /* OrganismV3ToV2.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = OrganismV3ToV2.xcmappingmodel; sourceTree = "<group>"; };
B52977D81B120B80003D50A5 /* ObserversViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserversViewController.swift; sourceTree = "<group>"; };
B52977DC1B120F3B003D50A5 /* TransactionsDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionsDemoViewController.swift; sourceTree = "<group>"; };
B52977DE1B120F83003D50A5 /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; };
B52977E01B120F8A003D50A5 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; };
B52977E31B121635003D50A5 /* Place.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Place.swift; sourceTree = "<group>"; };
B54AAD491AF4D26E00848AE0 /* LegacyDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LegacyDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
B54AAD4D1AF4D26E00848AE0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B54AAD4E1AF4D26E00848AE0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
B54AAD511AF4D26E00848AE0 /* LegacyDemo.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = LegacyDemo.xcdatamodel; sourceTree = "<group>"; };
B54AAD581AF4D26E00848AE0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
B54AAD5D1AF4D26E00848AE0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
B560070E1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV2ToV3MigrationPolicy.swift; sourceTree = "<group>"; };
B5635D182357F9F700B80E6B /* CollectionViewDemoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewDemoViewController.swift; sourceTree = "<group>"; };
B5635D1A2357FA4B00B80E6B /* PaletteCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteCollectionViewCell.swift; sourceTree = "<group>"; };
B566E3291B117B1F00F4F0C6 /* StackSetupDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StackSetupDemoViewController.swift; sourceTree = "<group>"; };
B566E3311B11DF3200F4F0C6 /* UserAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserAccount.swift; sourceTree = "<group>"; };
B56964C81B20AC780075EE4A /* CustomLoggerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomLoggerViewController.swift; sourceTree = "<group>"; };
B56964D61B231AE90075EE4A /* StackSetupDemo.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = StackSetupDemo.xcdatamodel; sourceTree = "<group>"; };
B56964D91B231BCA0075EE4A /* MaleAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaleAccount.swift; sourceTree = "<group>"; };
B56964DB1B231BCB0075EE4A /* FemaleAccount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FemaleAccount.swift; sourceTree = "<group>"; };
B569650B1B2B36E10075EE4A /* FetchingAndQueryingDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchingAndQueryingDemoViewController.swift; sourceTree = "<group>"; };
B56965171B2E20CC0075EE4A /* TimeZone.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimeZone.swift; sourceTree = "<group>"; };
B56965191B30888A0075EE4A /* FetchingResultsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchingResultsViewController.swift; sourceTree = "<group>"; };
B569651B1B30889A0075EE4A /* QueryingResultsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryingResultsViewController.swift; sourceTree = "<group>"; };
B56965281B3582D30075EE4A /* MigrationDemo.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MigrationDemo.xcdatamodel; sourceTree = "<group>"; };
B5AA37EE2357D30300FFD4B9 /* ColorsDemo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorsDemo.swift; sourceTree = "<group>"; };
B5BDC9211C202429008147CD /* CoreStore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = CoreStore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B5C37EE42357FEBE0035A20D /* PaletteCollectionSectionHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaletteCollectionSectionHeaderView.swift; sourceTree = "<group>"; };
B5E599311B5240F50084BD5F /* OrganismTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OrganismTableViewCell.swift; path = "LegacyDemo/MIgrations Demo/OrganismTableViewCell.swift"; sourceTree = SOURCE_ROOT; };
B5EE25801B36E1B00000406B /* MigrationDemoV2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MigrationDemoV2.xcdatamodel; sourceTree = "<group>"; };
B5EE25841B36E23C0000406B /* OrganismV1.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV1.swift; sourceTree = "<group>"; };
B5EE25861B36E2520000406B /* OrganismV2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV2.swift; sourceTree = "<group>"; };
B5EE25881B36E2750000406B /* MigrationDemoV3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MigrationDemoV3.xcdatamodel; sourceTree = "<group>"; };
B5EE258B1B36E40D0000406B /* MigrationsDemoViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationsDemoViewController.swift; sourceTree = "<group>"; };
B5EE259A1B3EA4890000406B /* OrganismV3.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismV3.swift; sourceTree = "<group>"; };
B5EE259D1B3EC1B20000406B /* OrganismProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrganismProtocol.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
B54AAD461AF4D26E00848AE0 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B501323523477D2300FC238B /* SwiftUI.framework in Frameworks */,
B5E89AD01C5292A2003B04A9 /* CoreStore.framework in Frameworks */,
B52977E11B120F8A003D50A5 /* CoreLocation.framework in Frameworks */,
B52977DF1B120F83003D50A5 /* MapKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
B50132222344E20B00FC238B /* SwiftUI Demo */ = {
isa = PBXGroup;
children = (
B50132232344E24300FC238B /* SwiftUIView.swift */,
B50132272344E5E900FC238B /* SwiftUIContainerViewController.swift */,
);
path = "SwiftUI Demo";
sourceTree = "<group>";
};
B503FADA1AFDC71700F90881 /* List and Object Observers Demo */ = {
isa = PBXGroup;
children = (
B5AA37EE2357D30300FFD4B9 /* ColorsDemo.swift */,
B52977D81B120B80003D50A5 /* ObserversViewController.swift */,
B503FADB1AFDC71700F90881 /* ListObserverDemoViewController.swift */,
B5635D182357F9F700B80E6B /* CollectionViewDemoViewController.swift */,
B503FADC1AFDC71700F90881 /* ObjectObserverDemoViewController.swift */,
B503FADD1AFDC71700F90881 /* Palette.swift */,
B503FADE1AFDC71700F90881 /* PaletteTableViewCell.swift */,
B5635D1A2357FA4B00B80E6B /* PaletteCollectionViewCell.swift */,
B5C37EE42357FEBE0035A20D /* PaletteCollectionSectionHeaderView.swift */,
);
path = "List and Object Observers Demo";
sourceTree = "<group>";
};
B52977DB1B120F2C003D50A5 /* Transactions Demo */ = {
isa = PBXGroup;
children = (
B52977E31B121635003D50A5 /* Place.swift */,
B52977DC1B120F3B003D50A5 /* TransactionsDemoViewController.swift */,
);
path = "Transactions Demo";
sourceTree = "<group>";
};
B52977E21B120F90003D50A5 /* Frameworks */ = {
isa = PBXGroup;
children = (
B501323423477D2300FC238B /* SwiftUI.framework */,
B52977E01B120F8A003D50A5 /* CoreLocation.framework */,
B5BDC9211C202429008147CD /* CoreStore.framework */,
B52977DE1B120F83003D50A5 /* MapKit.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
B54AAD401AF4D26E00848AE0 = {
isa = PBXGroup;
children = (
B52977E21B120F90003D50A5 /* Frameworks */,
B54AAD4B1AF4D26E00848AE0 /* LegacyDemo */,
B54AAD4A1AF4D26E00848AE0 /* Products */,
);
sourceTree = "<group>";
};
B54AAD4A1AF4D26E00848AE0 /* Products */ = {
isa = PBXGroup;
children = (
B54AAD491AF4D26E00848AE0 /* LegacyDemo.app */,
);
name = Products;
sourceTree = "<group>";
};
B54AAD4B1AF4D26E00848AE0 /* LegacyDemo */ = {
isa = PBXGroup;
children = (
B54AAD4E1AF4D26E00848AE0 /* AppDelegate.swift */,
B50132222344E20B00FC238B /* SwiftUI Demo */,
B566E3271B117AE700F4F0C6 /* Stack Setup Demo */,
B503FADA1AFDC71700F90881 /* List and Object Observers Demo */,
B52977DB1B120F2C003D50A5 /* Transactions Demo */,
B56965091B2B35370075EE4A /* Fetching and Querying Demo */,
B569652F1B3591460075EE4A /* Migrations Demo */,
B56964C61B20AC200075EE4A /* Loggers Demo */,
B54AAD571AF4D26E00848AE0 /* Main.storyboard */,
B54AAD5A1AF4D26E00848AE0 /* Images.xcassets */,
B54AAD5C1AF4D26E00848AE0 /* LaunchScreen.xib */,
B54AAD501AF4D26E00848AE0 /* LegacyDemo.xcdatamodeld */,
B56964D51B231AE90075EE4A /* StackSetupDemo.xcdatamodeld */,
B56965271B3582D30075EE4A /* MigrationDemo.xcdatamodeld */,
B54AAD4C1AF4D26E00848AE0 /* Supporting Files */,
);
path = LegacyDemo;
sourceTree = "<group>";
};
B54AAD4C1AF4D26E00848AE0 /* Supporting Files */ = {
isa = PBXGroup;
children = (
B54AAD4D1AF4D26E00848AE0 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
B566E3271B117AE700F4F0C6 /* Stack Setup Demo */ = {
isa = PBXGroup;
children = (
B56964DB1B231BCB0075EE4A /* FemaleAccount.swift */,
B56964D91B231BCA0075EE4A /* MaleAccount.swift */,
B566E3311B11DF3200F4F0C6 /* UserAccount.swift */,
B566E3291B117B1F00F4F0C6 /* StackSetupDemoViewController.swift */,
);
path = "Stack Setup Demo";
sourceTree = "<group>";
};
B56964C61B20AC200075EE4A /* Loggers Demo */ = {
isa = PBXGroup;
children = (
B56964C81B20AC780075EE4A /* CustomLoggerViewController.swift */,
);
path = "Loggers Demo";
sourceTree = "<group>";
};
B56965091B2B35370075EE4A /* Fetching and Querying Demo */ = {
isa = PBXGroup;
children = (
B56965171B2E20CC0075EE4A /* TimeZone.swift */,
B569650B1B2B36E10075EE4A /* FetchingAndQueryingDemoViewController.swift */,
B56965191B30888A0075EE4A /* FetchingResultsViewController.swift */,
B569651B1B30889A0075EE4A /* QueryingResultsViewController.swift */,
);
path = "Fetching and Querying Demo";
sourceTree = "<group>";
};
B569652F1B3591460075EE4A /* Migrations Demo */ = {
isa = PBXGroup;
children = (
B5EE259D1B3EC1B20000406B /* OrganismProtocol.swift */,
B5EE259A1B3EA4890000406B /* OrganismV3.swift */,
B5EE25861B36E2520000406B /* OrganismV2.swift */,
B5EE25841B36E23C0000406B /* OrganismV1.swift */,
B5EE258B1B36E40D0000406B /* MigrationsDemoViewController.swift */,
B5E599311B5240F50084BD5F /* OrganismTableViewCell.swift */,
B5125C111B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel */,
B560070E1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift */,
B5125C131B521BA7003A42C7 /* OrganismV3ToV2.xcmappingmodel */,
);
path = "Migrations Demo";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
B54AAD481AF4D26E00848AE0 /* LegacyDemo */ = {
isa = PBXNativeTarget;
buildConfigurationList = B54AAD6D1AF4D26E00848AE0 /* Build configuration list for PBXNativeTarget "LegacyDemo" */;
buildPhases = (
B54AAD451AF4D26E00848AE0 /* Sources */,
B54AAD461AF4D26E00848AE0 /* Frameworks */,
B54AAD471AF4D26E00848AE0 /* Resources */,
B5E89ACF1C52929C003B04A9 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = LegacyDemo;
productName = LegacyDemo;
productReference = B54AAD491AF4D26E00848AE0 /* LegacyDemo.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
B54AAD411AF4D26E00848AE0 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 1200;
ORGANIZATIONNAME = "John Rommel Estropia";
TargetAttributes = {
B54AAD481AF4D26E00848AE0 = {
CreatedOnToolsVersion = 6.3;
DevelopmentTeam = 2JT32EJ5BH;
LastSwiftMigration = 0900;
};
};
};
buildConfigurationList = B54AAD441AF4D26E00848AE0 /* Build configuration list for PBXProject "LegacyDemo" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = B54AAD401AF4D26E00848AE0;
productRefGroup = B54AAD4A1AF4D26E00848AE0 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
B54AAD481AF4D26E00848AE0 /* LegacyDemo */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
B54AAD471AF4D26E00848AE0 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B54AAD591AF4D26E00848AE0 /* Main.storyboard in Resources */,
B54AAD5E1AF4D26E00848AE0 /* LaunchScreen.xib in Resources */,
B54AAD5B1AF4D26E00848AE0 /* Images.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
B54AAD451AF4D26E00848AE0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B56965181B2E20CC0075EE4A /* TimeZone.swift in Sources */,
B5C37EE52357FEBE0035A20D /* PaletteCollectionSectionHeaderView.swift in Sources */,
B56965291B3582D30075EE4A /* MigrationDemo.xcdatamodeld in Sources */,
B5E599321B5240F50084BD5F /* OrganismTableViewCell.swift in Sources */,
B5EE25851B36E23C0000406B /* OrganismV1.swift in Sources */,
B52977DD1B120F3B003D50A5 /* TransactionsDemoViewController.swift in Sources */,
B52977E41B121635003D50A5 /* Place.swift in Sources */,
B569650C1B2B36E10075EE4A /* FetchingAndQueryingDemoViewController.swift in Sources */,
B569651A1B30888A0075EE4A /* FetchingResultsViewController.swift in Sources */,
B5EE25871B36E2520000406B /* OrganismV2.swift in Sources */,
B503FAE01AFDC71700F90881 /* ObjectObserverDemoViewController.swift in Sources */,
B52977D91B120B80003D50A5 /* ObserversViewController.swift in Sources */,
B56964C91B20AC780075EE4A /* CustomLoggerViewController.swift in Sources */,
B5635D192357F9F700B80E6B /* CollectionViewDemoViewController.swift in Sources */,
B566E32A1B117B1F00F4F0C6 /* StackSetupDemoViewController.swift in Sources */,
B56964DA1B231BCA0075EE4A /* MaleAccount.swift in Sources */,
B566E3321B11DF3200F4F0C6 /* UserAccount.swift in Sources */,
B54AAD521AF4D26E00848AE0 /* LegacyDemo.xcdatamodeld in Sources */,
B5EE259B1B3EA4890000406B /* OrganismV3.swift in Sources */,
B503FAE11AFDC71700F90881 /* Palette.swift in Sources */,
B503FAE21AFDC71700F90881 /* PaletteTableViewCell.swift in Sources */,
B560070F1B3EC90F00A9A8F9 /* OrganismV2ToV3MigrationPolicy.swift in Sources */,
B503FADF1AFDC71700F90881 /* ListObserverDemoViewController.swift in Sources */,
B54AAD4F1AF4D26E00848AE0 /* AppDelegate.swift in Sources */,
B50132282344E5E900FC238B /* SwiftUIContainerViewController.swift in Sources */,
B5635D1B2357FA4B00B80E6B /* PaletteCollectionViewCell.swift in Sources */,
B56964D71B231AE90075EE4A /* StackSetupDemo.xcdatamodeld in Sources */,
B56964DC1B231BCB0075EE4A /* FemaleAccount.swift in Sources */,
B5AA37EF2357D30300FFD4B9 /* ColorsDemo.swift in Sources */,
B5EE259E1B3EC1B20000406B /* OrganismProtocol.swift in Sources */,
B5EE258C1B36E40D0000406B /* MigrationsDemoViewController.swift in Sources */,
B50132242344E24300FC238B /* SwiftUIView.swift in Sources */,
B569651C1B30889A0075EE4A /* QueryingResultsViewController.swift in Sources */,
B5125C121B521B78003A42C7 /* OrganismV2ToV3.xcmappingmodel in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
B54AAD571AF4D26E00848AE0 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
B54AAD581AF4D26E00848AE0 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
B54AAD5C1AF4D26E00848AE0 /* LaunchScreen.xib */ = {
isa = PBXVariantGroup;
children = (
B54AAD5D1AF4D26E00848AE0 /* Base */,
);
name = LaunchScreen.xib;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
B54AAD6B1AF4D26E00848AE0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 5.0;
};
name = Debug;
};
B54AAD6C1AF4D26E00848AE0 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
SWIFT_VERSION = 5.0;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
B54AAD6E1AF4D26E00848AE0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 2JT32EJ5BH;
INFOPLIST_FILE = LegacyDemo/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.legacydemo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
};
name = Debug;
};
B54AAD6F1AF4D26E00848AE0 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = 2JT32EJ5BH;
INFOPLIST_FILE = LegacyDemo/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.johnestropia.legacydemo;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_SWIFT3_OBJC_INFERENCE = Off;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
B54AAD441AF4D26E00848AE0 /* Build configuration list for PBXProject "LegacyDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B54AAD6B1AF4D26E00848AE0 /* Debug */,
B54AAD6C1AF4D26E00848AE0 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
B54AAD6D1AF4D26E00848AE0 /* Build configuration list for PBXNativeTarget "LegacyDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
B54AAD6E1AF4D26E00848AE0 /* Debug */,
B54AAD6F1AF4D26E00848AE0 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCVersionGroup section */
B54AAD501AF4D26E00848AE0 /* LegacyDemo.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
B54AAD511AF4D26E00848AE0 /* LegacyDemo.xcdatamodel */,
);
currentVersion = B54AAD511AF4D26E00848AE0 /* LegacyDemo.xcdatamodel */;
path = LegacyDemo.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
};
B56964D51B231AE90075EE4A /* StackSetupDemo.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
B56964D61B231AE90075EE4A /* StackSetupDemo.xcdatamodel */,
);
currentVersion = B56964D61B231AE90075EE4A /* StackSetupDemo.xcdatamodel */;
path = StackSetupDemo.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
};
B56965271B3582D30075EE4A /* MigrationDemo.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
B5EE25881B36E2750000406B /* MigrationDemoV3.xcdatamodel */,
B5EE25801B36E1B00000406B /* MigrationDemoV2.xcdatamodel */,
B56965281B3582D30075EE4A /* MigrationDemo.xcdatamodel */,
);
currentVersion = B5EE25881B36E2750000406B /* MigrationDemoV3.xcdatamodel */;
path = MigrationDemo.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
};
/* End XCVersionGroup section */
};
rootObject = B54AAD411AF4D26E00848AE0 /* Project object */;
}

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:LegacyDemo.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -1,26 +0,0 @@
//
// AppDelegate.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/05/02.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
// MARK: - AppDelegate
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
// MARK: UIApplicationDelegate
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
return true
}
}

View File

@@ -1,52 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright © 2018 John Rommel Estropia. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<rect key="frame" x="20" y="439" width="440" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="CoreStoreIcon" translatesAutoresizingMaskIntoConstraints="NO" id="q8C-V6-gXH">
<rect key="frame" x="155" y="83" width="170" height="170"/>
</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="kId-c2-rCX">
<rect key="frame" x="20" y="273" width="440" height="57.5"/>
<fontDescription key="fontDescription" name="HelveticaNeue-UltraLight" family="Helvetica Neue" pointSize="50"/>
<color key="textColor" red="0.90744441747665405" green="0.9265514612197876" blue="0.93116652965545654" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="0.15542715787887573" green="0.2203737199306488" blue="0.2959403395652771" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
<constraint firstItem="q8C-V6-gXH" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" multiplier="0.7" id="QW6-8Y-w15"/>
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
<constraint firstItem="q8C-V6-gXH" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="fRb-1V-9iD"/>
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
<constraint firstItem="kId-c2-rCX" firstAttribute="top" secondItem="q8C-V6-gXH" secondAttribute="bottom" constant="20" id="s63-MP-ush"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="548" y="455"/>
</view>
</objects>
<resources>
<image name="CoreStoreIcon" width="170" height="170"/>
</resources>
</document>

File diff suppressed because it is too large Load Diff

View File

@@ -1,319 +0,0 @@
//
// FetchingAndQueryingDemoViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/12.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
import CoreStore
private struct Static {
static let timeZonesStack: DataStack = {
let dataStack = DataStack()
try! dataStack.addStorageAndWait(
SQLiteStore(
fileName: "TimeZoneDemo.sqlite",
configuration: "FetchingAndQueryingDemo",
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 = Int32(rawTimeZone.secondsFromGMT)
cachedTimeZone.hasDaylightSavingTime = rawTimeZone.isDaylightSavingTime
cachedTimeZone.daylightSavingTimeOffset = rawTimeZone.daylightSavingTimeOffset
}
}
)
return dataStack
}()
}
// MARK: - FetchingAndQueryingDemoViewController
class FetchingAndQueryingDemoViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
// MARK: UIViewController
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if self.didAppearOnce {
return
}
self.didAppearOnce = true
let alert = UIAlertController(
title: "Fetch and Query Demo",
message: "This demo shows how to execute fetches and queries.\n\nEach menu item executes and displays a preconfigured fetch/query.",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if let indexPath = sender as? IndexPath {
switch segue.destination {
case let controller as FetchingResultsViewController:
let item = self.fetchingItems[indexPath.row]
controller.set(timeZones: item.fetch(), title: item.title)
case let controller as QueryingResultsViewController:
let item = self.queryingItems[indexPath.row]
controller.set(value: item.query(), title: item.title)
default:
break
}
}
}
// MARK: UITableViewDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch self.segmentedControl?.selectedSegmentIndex {
case Section.fetching.rawValue?:
return self.fetchingItems.count
case Section.querying.rawValue?:
return self.queryingItems.count
default:
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell")!
switch self.segmentedControl?.selectedSegmentIndex {
case Section.fetching.rawValue?:
cell.textLabel?.text = self.fetchingItems[indexPath.row].title
case Section.querying.rawValue?:
cell.textLabel?.text = self.queryingItems[indexPath.row].title
default:
cell.textLabel?.text = nil
}
return cell
}
// MARK: UITableViewDelegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
switch self.segmentedControl?.selectedSegmentIndex {
case Section.fetching.rawValue?:
self.performSegue(withIdentifier: "FetchingResultsViewController", sender: indexPath)
case Section.querying.rawValue?:
self.performSegue(withIdentifier: "QueryingResultsViewController", sender: indexPath)
default:
break
}
}
// MARK: Private
private enum Section: Int {
case fetching
case querying
}
private let fetchingItems = [
(
title: "All Time Zones",
fetch: { () -> [TimeZone] in
return try! Static.timeZonesStack.fetchAll(
From<TimeZone>()
.orderBy(.ascending(\.name))
)
}
),
(
title: "Time Zones in Asia",
fetch: { () -> [TimeZone] in
return try! Static.timeZonesStack.fetchAll(
From<TimeZone>()
.where(
format: "%K BEGINSWITH[c] %@",
#keyPath(TimeZone.name),
"Asia"
)
.orderBy(.ascending(\.secondsFromGMT))
)
}
),
(
title: "Time Zones in America and Europe",
fetch: { () -> [TimeZone] in
return try! Static.timeZonesStack.fetchAll(
From<TimeZone>()
.where(
format: "%K BEGINSWITH[c] %@ OR %K BEGINSWITH[c] %@",
#keyPath(TimeZone.name),
"America",
#keyPath(TimeZone.name),
"Europe"
)
.orderBy(.ascending(\.secondsFromGMT))
)
}
),
(
title: "All Time Zones Except America",
fetch: { () -> [TimeZone] in
return try! Static.timeZonesStack.fetchAll(
From<TimeZone>()
.where(
format: "%K BEGINSWITH[c] %@",
#keyPath(TimeZone.name),
"America"
)
.orderBy(.ascending(\.secondsFromGMT))
)
}
),
(
title: "Time Zones with Summer Time",
fetch: { () -> [TimeZone] in
return try! Static.timeZonesStack.fetchAll(
From<TimeZone>()
.where(\.hasDaylightSavingTime == true)
.orderBy(.ascending(\.name))
)
}
)
]
private let queryingItems: [(title: String, query: () -> Any)] = [
(
title: "Number of Time Zones",
query: { () -> Any in
return try! Static.timeZonesStack.queryValue(
From<TimeZone>()
.select(NSNumber.self, .count(\.name))
)!
}
),
(
title: "Abbreviation For Tokyo's Time Zone",
query: { () -> Any in
return try! Static.timeZonesStack.queryValue(
From<TimeZone>()
.select(String.self, .attribute(\.abbreviation))
.where(format: "%K ENDSWITH[c] %@", #keyPath(TimeZone.name), "Tokyo")
)!
}
),
(
title: "All Abbreviations",
query: { () -> Any in
return try! Static.timeZonesStack.queryAttributes(
From<TimeZone>()
.select(
NSDictionary.self,
.attribute(\.name),
.attribute(\.abbreviation)
)
.orderBy(.ascending(\.name))
)
}
),
(
title: "Number of Countries per Time Zone",
query: { () -> Any in
return try! Static.timeZonesStack.queryAttributes(
From<TimeZone>()
.select(
NSDictionary.self,
.count(\.abbreviation),
.attribute(\.abbreviation)
)
.groupBy(\.abbreviation)
.orderBy(
.ascending(\.secondsFromGMT),
.ascending(\.name)
)
)
}
),
(
title: "Number of Countries with Summer Time",
query: { () -> Any in
return try! Static.timeZonesStack.queryAttributes(
From<TimeZone>()
.select(
NSDictionary.self,
.count(\.hasDaylightSavingTime, as: "numberOfCountries"),
.attribute(\.hasDaylightSavingTime)
)
.groupBy(\.hasDaylightSavingTime)
.orderBy(
.descending(\.hasDaylightSavingTime),
.ascending(\.name)
)
)
}
)
]
var didAppearOnce = false
@IBOutlet dynamic weak var segmentedControl: UISegmentedControl?
@IBOutlet dynamic weak var tableView: UITableView?
@IBAction dynamic func segmentedControlValueChanged(_ sender: AnyObject?) {
self.tableView?.reloadData()
}
}

View File

@@ -1,68 +0,0 @@
//
// FetchingResultsViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/17.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
// MARK: - FetchingResultsViewController
class FetchingResultsViewController: UITableViewController {
// MARK: Public
func set(timeZones: [TimeZone]?, title: String) {
self.timeZones += timeZones ?? []
self.sectionTitle = title
self.tableView?.reloadData()
}
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.estimatedRowHeight = 60
self.tableView.rowHeight = UITableView.automaticDimension
}
// MARK: UITableViewDataSource
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.timeZones.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath)
let timeZone = self.timeZones[indexPath.row]
cell.textLabel?.text = timeZone.name
cell.detailTextLabel?.text = timeZone.abbreviation
return cell
}
// MARK: UITableViewDelegate
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.sectionTitle
}
// MARK: Private
var timeZones = [TimeZone]()
var sectionTitle: String?
}

View File

@@ -1,88 +0,0 @@
//
// QueryingResultsViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/17.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
class QueryingResultsViewController: UITableViewController {
// MARK: Public
func set(value: Any?, title: String) {
switch value {
case (let array as [Any])?:
self.values = array.map { (item: Any) -> (title: String, detail: String) in
(
title: String(describing: item),
detail: String(reflecting: type(of: item))
)
}
case let item?:
self.values = [
(
title: String(describing: item),
detail: String(reflecting: type(of: item))
)
]
default:
self.values = []
}
self.sectionTitle = title
self.tableView?.reloadData()
}
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.estimatedRowHeight = 60
self.tableView.rowHeight = UITableView.automaticDimension
}
// MARK: UITableViewDataSource
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.values.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath)
let value = self.values[indexPath.row]
cell.textLabel?.text = value.title
cell.detailTextLabel?.text = value.detail
return cell
}
// MARK: UITableViewDelegate
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.sectionTitle
}
// MARK: Private
var values: [(title: String, detail: String)] = []
var sectionTitle: String?
}

View File

@@ -1,20 +0,0 @@
//
// TimeZone.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/15.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import Foundation
import CoreData
class TimeZone: NSManagedObject {
@NSManaged var secondsFromGMT: Int32
@NSManaged var abbreviation: String
@NSManaged var hasDaylightSavingTime: Bool
@NSManaged var daylightSavingTimeOffset: Double
@NSManaged var name: String
}

View File

@@ -1,114 +0,0 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-60@3x-1.png",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-76.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-76@2x.png",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "83.5x83.5",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Mask + Oval 1 + Oval 1 + Oval 1.png",
"scale" : "1x"
},
{
"idiom" : "car",
"size" : "60x60",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "car",
"filename" : "Icon-60@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

View File

@@ -1,6 +0,0 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -1,21 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "CoreStoreIcon@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -1,12 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "first.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -1,12 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "second.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -1,56 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>CoreStore</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>6.3.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>4</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>
<key>UIStatusBarTintParameters</key>
<dict>
<key>UINavigationBar</key>
<dict>
<key>Style</key>
<string>UIBarStyleDefault</string>
<key>Translucent</key>
<false/>
</dict>
</dict>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
<key>UIUserInterfaceStyle</key>
<string>Light</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="15702" systemVersion="18G1012" minimumToolsVersion="Xcode 7.3" sourceLanguage="Objective-C" userDefinedModelVersionIdentifier="">
<entity name="Place" representedClassName="LegacyDemo.Place" syncable="YES">
<attribute name="latitude" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="NO" syncable="YES"/>
<attribute name="longitude" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="NO" syncable="YES"/>
<attribute name="subtitle" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="title" optional="YES" attributeType="String" syncable="YES"/>
</entity>
<entity name="TimeZone" representedClassName="LegacyDemo.TimeZone" syncable="YES">
<attribute name="abbreviation" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="daylightSavingTimeOffset" optional="YES" attributeType="Double" defaultValueString="0.0" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasDaylightSavingTime" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="secondsFromGMT" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="NO" syncable="YES"/>
</entity>
<configuration name="FetchingAndQueryingDemo">
<memberEntity name="TimeZone"/>
</configuration>
<configuration name="TransactionsDemo">
<memberEntity name="Place"/>
</configuration>
<elements>
<element name="Place" positionX="261" positionY="225" width="128" height="103"/>
<element name="TimeZone" positionX="297" positionY="270" width="128" height="120"/>
</elements>
</model>

View File

@@ -1,168 +0,0 @@
//
// CollectionViewDemoViewController.swift
// LegacyDemo
//
// Created by John Estropia on 2019/10/17.
// Copyright © 2019 John Rommel Estropia. All rights reserved.
//
import UIKit
import CoreStore
// MARK: - CollectionViewDemoViewController
final class CollectionViewDemoViewController: UICollectionViewController {
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
let navigationItem = self.navigationItem
navigationItem.leftBarButtonItems = [
self.editButtonItem,
UIBarButtonItem(
barButtonSystemItem: .trash,
target: self,
action: #selector(self.resetBarButtonItemTouched(_:))
)
]
let filterBarButton = UIBarButtonItem(
title: ColorsDemo.filter.rawValue,
style: .plain,
target: self,
action: #selector(self.filterBarButtonItemTouched(_:))
)
navigationItem.rightBarButtonItems = [
UIBarButtonItem(
barButtonSystemItem: .add,
target: self,
action: #selector(self.addBarButtonItemTouched(_:))
),
UIBarButtonItem(
barButtonSystemItem: .refresh,
target: self,
action: #selector(self.shuffleBarButtonItemTouched(_:))
),
filterBarButton
]
self.filterBarButton = filterBarButton
self.dataSource = DiffableDataSource.CollectionViewAdapter<Palette>(
collectionView: self.collectionView,
dataStack: ColorsDemo.stack,
cellProvider: { (collectionView, indexPath, palette) in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PaletteCollectionViewCell", for: indexPath) as! PaletteCollectionViewCell
cell.colorView?.backgroundColor = palette.color
cell.label?.text = palette.colorText
return cell
},
supplementaryViewProvider: { (collectionView, kind, indexPath) in
switch kind {
case UICollectionView.elementKindSectionHeader:
let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "PaletteCollectionSectionHeaderView", for: indexPath) as! PaletteCollectionSectionHeaderView
view.label?.text = ColorsDemo.palettes.snapshot.sectionIDs[indexPath.section]
return view
default:
return nil
}
}
)
ColorsDemo.palettes.addObserver(self) { [weak self] (listPublisher) in
guard let self = self else {
return
}
self.filterBarButton?.title = ColorsDemo.filter.rawValue
self.dataSource?.apply(listPublisher.snapshot, animatingDifferences: true)
}
self.dataSource?.apply(ColorsDemo.palettes.snapshot, animatingDifferences: false)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
switch (segue.identifier, segue.destination, sender) {
case ("ObjectObserverDemoViewController"?, let destinationViewController as ObjectObserverDemoViewController, let palette as ObjectPublisher<Palette>):
destinationViewController.setPalette(palette)
default:
break
}
}
// MARK: UICollectionViewDelegate
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
collectionView.deselectItem(at: indexPath, animated: true)
self.performSegue(
withIdentifier: "ObjectObserverDemoViewController",
sender: ColorsDemo.palettes.snapshot[indexPath]
)
}
// MARK: Private
private var filterBarButton: UIBarButtonItem?
private var dataSource: DiffableDataSource.CollectionViewAdapter<Palette>?
deinit {
ColorsDemo.palettes.removeObserver(self)
}
@IBAction private dynamic func resetBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
try transaction.deleteAll(From<Palette>())
},
completion: { _ in }
)
}
@IBAction private dynamic func filterBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.filter = ColorsDemo.filter.next()
}
@IBAction private dynamic func addBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
_ = transaction.create(Into<Palette>())
},
completion: { _ in }
)
}
@IBAction private dynamic func shuffleBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
for palette in try transaction.fetchAll(From<Palette>()) {
palette.hue = Palette.randomHue()
palette.colorName = nil
}
},
completion: { _ in }
)
}
}

View File

@@ -1,88 +0,0 @@
//
// ColorsDemo.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2019/10/17.
// Copyright © 2019 John Rommel Estropia. All rights reserved.
//
import Foundation
import CoreStore
// MARK: - ColorsDemo
struct ColorsDemo {
enum Filter: String {
case all = "All Colors"
case light = "Light Colors"
case dark = "Dark Colors"
func next() -> Filter {
switch self {
case .all: return .light
case .light: return .dark
case .dark: return .all
}
}
func whereClause() -> Where<Palette> {
switch self {
case .all: return .init()
case .light: return (\Palette.$brightness >= 0.9)
case .dark: return (\Palette.$brightness <= 0.4)
}
}
}
static var filter = Filter.all {
didSet {
try! self.palettes.refetch(
From<Palette>()
.sectionBy(\.$colorName)
.where(self.filter.whereClause())
.orderBy(.ascending(\.$hue))
)
}
}
static let stack: DataStack = {
let dataStack = DataStack(
CoreStoreSchema(
modelVersion: "ColorsDemo",
entities: [
Entity<Palette>("Palette"),
],
versionLock: [
"Palette": [0x8c25aa53c7c90a28, 0xa243a34d25f1a3a7, 0x56565b6935b6055a, 0x4f988bb257bf274f]
]
)
)
try! dataStack.addStorageAndWait(
SQLiteStore(
fileName: "ColorsDemo.sqlite",
localStorageOptions: .recreateStoreOnModelMismatch
)
)
return dataStack
}()
static let palettes: ListPublisher<Palette> = {
return ColorsDemo.stack.publishList(
From<Palette>()
.sectionBy(\.$colorName)
.orderBy(.ascending(\.$hue))
)
}()
}

View File

@@ -1,181 +0,0 @@
//
// ListObserverDemoViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/05/02.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
import CoreStore
// MARK: - ListObserverDemoViewController
final class ListObserverDemoViewController: UITableViewController {
// MARK: - EditableDataSource
final class EditableDataSource: DiffableDataSource.TableViewAdapter<Palette> {
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
switch editingStyle {
case .delete:
let palette = ColorsDemo.palettes.snapshot[indexPath]
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
transaction.delete(palette)
},
completion: { _ in }
)
default:
break
}
}
}
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
let navigationItem = self.navigationItem
navigationItem.leftBarButtonItems = [
self.editButtonItem,
UIBarButtonItem(
barButtonSystemItem: .trash,
target: self,
action: #selector(self.resetBarButtonItemTouched(_:))
)
]
let filterBarButton = UIBarButtonItem(
title: ColorsDemo.filter.rawValue,
style: .plain,
target: self,
action: #selector(self.filterBarButtonItemTouched(_:))
)
navigationItem.rightBarButtonItems = [
UIBarButtonItem(
barButtonSystemItem: .add,
target: self,
action: #selector(self.addBarButtonItemTouched(_:))
),
UIBarButtonItem(
barButtonSystemItem: .refresh,
target: self,
action: #selector(self.shuffleBarButtonItemTouched(_:))
),
filterBarButton
]
self.filterBarButton = filterBarButton
self.dataSource = EditableDataSource(
tableView: self.tableView,
dataStack: ColorsDemo.stack,
cellProvider: { (tableView, indexPath, palette) in
let cell = tableView.dequeueReusableCell(withIdentifier: "PaletteTableViewCell") as! PaletteTableViewCell
cell.colorView?.backgroundColor = palette.color
cell.label?.text = palette.colorText
return cell
}
)
ColorsDemo.palettes.addObserver(self) { [weak self] (listPublisher) in
guard let self = self else {
return
}
self.filterBarButton?.title = ColorsDemo.filter.rawValue
self.dataSource?.apply(listPublisher.snapshot, animatingDifferences: true)
}
self.dataSource?.apply(ColorsDemo.palettes.snapshot, animatingDifferences: false)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
switch (segue.identifier, segue.destination, sender) {
case ("ObjectObserverDemoViewController"?, let destinationViewController as ObjectObserverDemoViewController, let palette as ObjectPublisher<Palette>):
destinationViewController.setPalette(palette)
default:
break
}
}
// MARK: UITableViewDelegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
self.performSegue(
withIdentifier: "ObjectObserverDemoViewController",
sender: ColorsDemo.palettes.snapshot[indexPath]
)
}
// MARK: Private
private var filterBarButton: UIBarButtonItem?
private var dataSource: DiffableDataSource.TableViewAdapter<Palette>?
deinit {
ColorsDemo.palettes.removeObserver(self)
}
@IBAction private dynamic func resetBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
try transaction.deleteAll(From<Palette>())
},
completion: { _ in }
)
}
@IBAction private dynamic func filterBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.filter = ColorsDemo.filter.next()
}
@IBAction private dynamic func addBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
_ = transaction.create(Into<Palette>())
},
completion: { _ in }
)
}
@IBAction private dynamic func shuffleBarButtonItemTouched(_ sender: AnyObject?) {
ColorsDemo.stack.perform(
asynchronous: { (transaction) in
for palette in try transaction.fetchAll(From<Palette>()) {
palette.hue = Palette.randomHue()
palette.colorName = nil
}
},
completion: { _ in }
)
}
}

View File

@@ -1,192 +0,0 @@
//
// ObjectObserverDemoViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/05/06.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
import CoreStore
// MARK: - ObjectObserverDemoViewController
class ObjectObserverDemoViewController: UIViewController, ObjectObserver {
func setPalette<O: ObjectRepresentation>(_ newValue: O?) where O.ObjectType == Palette {
guard self.monitor?.object?.objectID() != newValue?.objectID() else {
return
}
if let newValue = newValue {
self.monitor = newValue.asReadOnly(in: ColorsDemo.stack).map(ColorsDemo.stack.monitorObject(_:))
}
else {
self.monitor = nil
}
}
// MARK: NSObject
deinit {
self.monitor?.removeObserver(self)
}
// MARK: UIViewController
required init?(coder aDecoder: NSCoder) {
if let palette = try! ColorsDemo.stack.fetchOne(From<Palette>().orderBy(.ascending(\.$hue))) {
self.monitor = ColorsDemo.stack.monitorObject(palette)
}
else {
_ = try? ColorsDemo.stack.perform(
synchronous: { (transaction) in
_ = transaction.create(Into<Palette>())
}
)
let palette = try! ColorsDemo.stack.fetchOne(From<Palette>().orderBy(.ascending(\.$hue)))!
self.monitor = ColorsDemo.stack.monitorObject(palette)
}
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
self.monitor?.addObserver(self)
if let palette = self.monitor?.object {
self.reloadPaletteInfo(palette, changedKeys: nil)
}
}
// MARK: ObjectObserver
func objectMonitor(_ monitor: ObjectMonitor<Palette>, didUpdateObject object: Palette, changedPersistentKeys: Set<KeyPathString>) {
self.reloadPaletteInfo(object, changedKeys: changedPersistentKeys)
}
func objectMonitor(_ monitor: ObjectMonitor<Palette>, didDeleteObject object: Palette) {
self.navigationItem.rightBarButtonItem?.isEnabled = false
self.colorNameLabel?.alpha = 0.3
self.colorView?.alpha = 0.3
self.hsbLabel?.text = "Deleted"
self.hsbLabel?.textColor = UIColor.red
self.hueSlider?.isEnabled = false
self.saturationSlider?.isEnabled = false
self.brightnessSlider?.isEnabled = false
}
// MARK: Private
var monitor: ObjectMonitor<Palette>?
@IBOutlet weak var colorNameLabel: UILabel?
@IBOutlet weak var colorView: UIView?
@IBOutlet weak var hsbLabel: UILabel?
@IBOutlet weak var dateLabel: UILabel?
@IBOutlet weak var hueSlider: UISlider?
@IBOutlet weak var saturationSlider: UISlider?
@IBOutlet weak var brightnessSlider: UISlider?
@IBAction dynamic func hueSliderValueDidChange(_ sender: AnyObject?) {
let hue = self.hueSlider?.value ?? 0
ColorsDemo.stack.perform(
asynchronous: { [weak self] (transaction) in
if let palette = transaction.edit(self?.monitor?.object) {
palette.hue = Int(hue)
}
},
completion: { _ in }
)
}
@IBAction dynamic func saturationSliderValueDidChange(_ sender: AnyObject?) {
let saturation = self.saturationSlider?.value ?? 0
ColorsDemo.stack.perform(
asynchronous: { [weak self] (transaction) in
if let palette = transaction.edit(self?.monitor?.object) {
palette.saturation = saturation
}
},
completion: { _ in }
)
}
@IBAction dynamic func brightnessSliderValueDidChange(_ sender: AnyObject?) {
let brightness = self.brightnessSlider?.value ?? 0
ColorsDemo.stack.perform(
asynchronous: { [weak self] (transaction) in
if let palette = transaction.edit(self?.monitor?.object) {
palette.brightness = brightness
}
},
completion: { _ in }
)
}
@IBAction dynamic func deleteBarButtonTapped(_ sender: AnyObject?) {
ColorsDemo.stack.perform(
asynchronous: { [weak self] (transaction) in
transaction.delete(self?.monitor?.object)
},
completion: { _ in }
)
}
func reloadPaletteInfo(_ palette: Palette, changedKeys: Set<String>?) {
self.colorNameLabel?.text = palette.colorName
let color = palette.color
self.colorNameLabel?.textColor = color
self.colorView?.backgroundColor = color
self.hsbLabel?.text = palette.colorText
if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.$hue)) == true {
self.hueSlider?.value = Float(palette.hue)
}
if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.$saturation)) == true {
self.saturationSlider?.value = palette.saturation
}
if changedKeys == nil || changedKeys?.contains(String(keyPath: \Palette.$brightness)) == true {
self.brightnessSlider?.value = palette.brightness
}
}
}

View File

@@ -1,59 +0,0 @@
//
// ObserversViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/05/24.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
// MARK: - ObserversViewController
class ObserversViewController: UIViewController {
// MARK: UIViewController
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let alert = UIAlertController(
title: "Observers Demo",
message: "This demo shows how to observe changes to a list of objects. The top and bottom view controllers both observe a single shared \"ListMonitor\" instance.\n\nTap on a row to see how to observe changes made to a single object using a \"ObjectMonitor\".",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
// MARK: Private
@IBOutlet private dynamic weak var toggleTopBarButtonItem: UIBarButtonItem?
@IBOutlet private dynamic weak var toggleBottomBarButtonItem: UIBarButtonItem?
@IBOutlet private dynamic weak var stackView: UIStackView?
@IBOutlet private dynamic weak var topContainerView: UIView?
@IBOutlet private dynamic weak var bottomContainerView: UIView?
@IBAction private dynamic func toggleTopContainerView() {
UIView.animate(withDuration: 0.2) {
self.topContainerView!.isHidden.toggle()
}
self.toggleTopBarButtonItem!.isEnabled = !self.bottomContainerView!.isHidden
self.toggleBottomBarButtonItem!.isEnabled = !self.topContainerView!.isHidden
}
@IBAction private dynamic func toggleBottomContainerView() {
UIView.animate(withDuration: 0.2) {
self.bottomContainerView!.isHidden.toggle()
}
self.toggleTopBarButtonItem!.isEnabled = !self.bottomContainerView!.isHidden
self.toggleBottomBarButtonItem!.isEnabled = !self.topContainerView!.isHidden
}
}

View File

@@ -1,86 +0,0 @@
//
// Palette.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/05/05.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import Foundation
import UIKit
import CoreData
import CoreStore
// MARK: - Palette
final class Palette: CoreStoreObject {
@Field.Stored(
"hue",
dynamicInitialValue: { Palette.randomHue() }
)
var hue: Int
@Field.Stored("saturation")
var saturation: Float = 1
@Field.Stored(
"brightness",
dynamicInitialValue: { Palette.randomBrightness() }
)
var brightness: Float
@Field.Virtual(
"colorName",
customGetter: { object, field in
if let colorName = field.primitiveValue {
return colorName
}
let colorName: String
switch object.$hue.value {
case 0 ..< 20: colorName = "Lower Reds"
case 20 ..< 57: colorName = "Oranges and Browns"
case 57 ..< 90: colorName = "Yellow-Greens"
case 90 ..< 159: colorName = "Greens"
case 159 ..< 197: colorName = "Blue-Greens"
case 197 ..< 241: colorName = "Blues"
case 241 ..< 297: colorName = "Violets"
case 297 ..< 331: colorName = "Magentas"
case 331 ..< 360: colorName = "Upper Reds"
default: colorName = "<Invalid>"
}
field.primitiveValue = colorName
return colorName
}
)
var colorName: String!
static func randomHue() -> Int {
return Int.random(in: 0 ..< 360)
}
static func randomBrightness() -> Float {
return (Float.random(in: 0 ..< 70) + 30) / 100.0
}
}
extension Palette {
var color: UIColor {
return UIColor(
hue: CGFloat(self.hue) / 360.0,
saturation: CGFloat(self.saturation),
brightness: CGFloat(self.brightness),
alpha: 1.0
)
}
var colorText: String {
return "H: \(self.hue)˚, S: \(round(self.saturation * 100.0))%, B: \(round(self.brightness * 100.0))%"
}
}

View File

@@ -1,17 +0,0 @@
//
// PaletteCollectionSectionHeaderView.swift
// LegacyDemo
//
// Created by John Estropia on 2019/10/17.
// Copyright © 2019 John Rommel Estropia. All rights reserved.
//
import UIKit
// MARK: - PaletteCollectionSectionHeaderView
final class PaletteCollectionSectionHeaderView: UICollectionReusableView {
@IBOutlet weak var label: UILabel?
}

View File

@@ -1,18 +0,0 @@
//
// PaletteCollectionViewCell.swift
// LegacyDemo
//
// Created by John Estropia on 2019/10/17.
// Copyright © 2019 John Rommel Estropia. All rights reserved.
//
import UIKit
// MARK: - PaletteCollectionViewCell
final class PaletteCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var colorView: UIView?
@IBOutlet weak var label: UILabel?
}

View File

@@ -1,18 +0,0 @@
//
// PaletteTableViewCell.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/05/05.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
// MARK: - PaletteTableViewCell
final class PaletteTableViewCell: UITableViewCell {
@IBOutlet weak var colorView: UIView?
@IBOutlet weak var label: UILabel?
}

View File

@@ -1,126 +0,0 @@
//
// CustomLoggerViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/05.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
import CoreStore
// MARK: - CustomLoggerViewController
class CustomLoggerViewController: UIViewController, CoreStoreLogger {
// MARK: NSObject
let dataStack = DataStack()
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
try! self.dataStack.addStorageAndWait(SQLiteStore(fileName: "emptyStore.sqlite"))
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
CoreStoreDefaults.logger = self
let alert = UIAlertController(
title: "Logger Demo",
message: "This demo shows how to plug-in any logging framework to CoreStore.\n\nThe view controller implements CoreStoreLogger and appends all logs to the text view.",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
CoreStoreDefaults.logger = DefaultLogger()
}
// MARK: CoreStoreLogger
func log(level: LogLevel, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
DispatchQueue.main.async { [weak self] in
let levelString: String
switch level {
case .trace: levelString = "Trace"
case .notice: levelString = "Notice"
case .warning: levelString = "Warning"
case .fatal: levelString = "Fatal"
}
self?.textView?.insertText("\((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Log:\(levelString)] \(message)\n\n")
}
}
func log(error: CoreStoreError, message: String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
DispatchQueue.main.async { [weak self] in
self?.textView?.insertText("\((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Error] \(message): \(error)\n\n")
}
}
func assert(_ condition: @autoclosure () -> Bool, message: @autoclosure () -> String, fileName: StaticString, lineNumber: Int, functionName: StaticString) {
if condition() {
return
}
let messageString = message()
DispatchQueue.main.async { [weak self] in
self?.textView?.insertText("\((String(describing: fileName) as NSString).lastPathComponent):\(lineNumber) \(functionName)\n ↪︎ [Assert] \(messageString)\n\n")
}
}
// MARK: Private
@IBOutlet dynamic weak var textView: UITextView?
@IBOutlet dynamic weak var segmentedControl: UISegmentedControl?
@IBAction dynamic func segmentedControlValueChanged(_ sender: AnyObject?) {
switch self.segmentedControl?.selectedSegmentIndex {
case 0?:
let request = NSFetchRequest<NSFetchRequestResult>()
Where<NSManagedObject>(true).applyToFetchRequest(request)
Where<NSManagedObject>(false).applyToFetchRequest(request)
case 1?:
_ = try? dataStack.addStorageAndWait(
SQLiteStore(
fileName: "emptyStore.sqlite",
configuration: "invalidStore"
)
)
case 2?:
DispatchQueue.global(qos: .background).async {
_ = try! self.dataStack.fetchOne(From<Place>())
}
default:
return
}
}
}

View File

@@ -1,445 +0,0 @@
//
// MigrationsDemoViewController.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/21.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
import CoreStore
// MARK: - MigrationsDemoViewController
class MigrationsDemoViewController: UIViewController, ListObserver, UITableViewDataSource, UITableViewDelegate {
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
if let segmentedControl = self.segmentedControl {
for (index, model) in self.models.enumerated() {
segmentedControl.setTitle(
model.label,
forSegmentAt: index
)
}
}
self.set(dataStack: nil, model: nil, scrollToSelection: false)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let alert = UIAlertController(
title: "Migrations Demo",
message: "This demo shows how to run progressive migrations and how to support multiple model versions in a single project.\n\nThe persistent store contains 10000 organisms, which gain/lose properties when the migration evolves/devolves them.\n\nYou can use the \"mutate\" button to change an organism's properties then migrate to a different model to see how its value gets affected.",
preferredStyle: .alert
)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
let modelMetadata = withExtendedLifetime(DataStack(xcodeModelName: "MigrationDemo")) {
(dataStack: DataStack) -> ModelMetadata in
let models = self.models
let migrations = try! dataStack.requiredMigrationsForStorage(
SQLiteStore(fileName: "MigrationDemo.sqlite")
)
guard let storeVersion = migrations.first?.sourceVersion else {
return models.first!
}
for model in models {
if model.schemaHistory.currentModelVersion == storeVersion {
return model
}
}
return models.first!
}
self.selectModelVersion(modelMetadata)
}
// MARK: ListObserver
func listMonitorWillChange(_ monitor: ListMonitor<NSManagedObject>) { }
func listMonitorDidChange(_ monitor: ListMonitor<NSManagedObject>) {
if self.lastSelectedIndexPath == nil,
let numberOfObjectsInSection = self.listMonitor?.numberOfObjects(in: 0),
numberOfObjectsInSection > 0 {
self.tableView?.reloadData()
self.setSelectedIndexPath(IndexPath(row: 0, section: 0), scrollToSelection: false)
}
else {
self.updateDisplay(reloadData: true, scrollToSelection: true, animated: true)
}
}
func listMonitorDidRefetch(_ monitor: ListMonitor<NSManagedObject>) {
self.listMonitorDidChange(monitor)
}
// MARK: UITableViewDataSource
@objc dynamic func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.listMonitor?.numberOfObjects(in: 0) ?? 0
}
@objc dynamic func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "OrganismTableViewCell", for: indexPath) as! OrganismTableViewCell
let dna = (self.listMonitor?[indexPath] as? OrganismProtocol)?.dna.description ?? ""
cell.dnaLabel?.text = "DNA: \(dna)"
cell.mutateButtonHandler = { [weak self] () -> Void in
guard let `self` = self,
let dataStack = self.dataStack,
let organism = self.listMonitor?[indexPath] else {
return
}
self.setSelectedIndexPath(indexPath, scrollToSelection: false)
self.setEnabled(false)
dataStack.perform(
asynchronous: { (transaction) in
let organism = transaction.edit(organism) as! OrganismProtocol
organism.mutate()
},
completion: { [weak self] _ in
self?.setEnabled(true)
}
)
}
return cell
}
// MARK: UITableViewDelegate
@objc dynamic func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.setSelectedIndexPath(indexPath, scrollToSelection: false)
}
// MARK: Private
private typealias ModelMetadata = (label: String, entityType: NSManagedObject.Type, schemaHistory: SchemaHistory)
private let models: [ModelMetadata] = [
(
label: "Model V1",
entityType: OrganismV1.self,
schemaHistory: SchemaHistory(
XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
),
migrationChain: ["MigrationDemoV3", "MigrationDemoV2", "MigrationDemo"]
)
),
(
label: "Model V2",
entityType: OrganismV2.self,
schemaHistory: SchemaHistory(
XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: [
"MigrationDemo": "MigrationDemoV2",
"MigrationDemoV3": "MigrationDemoV2"
]
),
migrationChain: [
"MigrationDemo": "MigrationDemoV2",
"MigrationDemoV3": "MigrationDemoV2"
]
)
),
(
label: "Model V3",
entityType: OrganismV3.self,
schemaHistory: SchemaHistory(
XcodeDataModelSchema.from(
modelName: "MigrationDemo",
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
),
migrationChain: ["MigrationDemo", "MigrationDemoV2", "MigrationDemoV3"]
)
)
]
private var _listMonitor: ListMonitor<NSManagedObject>?
private var listMonitor: ListMonitor<NSManagedObject>? {
return self._listMonitor
}
private var _dataStack: DataStack?
private var dataStack: DataStack? {
return self._dataStack
}
private var _lastSelectedIndexPath: IndexPath?
private var lastSelectedIndexPath: IndexPath? {
return self._lastSelectedIndexPath
}
private func setSelectedIndexPath(_ indexPath: IndexPath, scrollToSelection: Bool) {
self._lastSelectedIndexPath = indexPath
self.updateDisplay(reloadData: false, scrollToSelection: scrollToSelection, animated: true)
}
@IBOutlet private dynamic weak var headerContainer: UIView?
@IBOutlet private dynamic weak var titleLabel: UILabel?
@IBOutlet private dynamic weak var organismLabel: UILabel?
@IBOutlet private dynamic weak var segmentedControl: UISegmentedControl?
@IBOutlet private dynamic weak var progressView: UIProgressView?
@IBOutlet private dynamic weak var tableView: UITableView?
@IBAction private dynamic func segmentedControlValueChanged(_ sender: AnyObject?) {
guard let index = self.segmentedControl?.selectedSegmentIndex else {
return
}
self.selectModelVersion(self.models[index])
}
private func selectModelVersion(_ model: ModelMetadata) {
if self.dataStack?.modelVersion == model.schemaHistory.currentModelVersion {
return
}
self.set(dataStack: nil, model: nil, scrollToSelection: false) // explicitly trigger NSPersistentStore cleanup by deallocating the stack
let dataStack = DataStack(schemaHistory: model.schemaHistory)
self.setEnabled(false)
let progress = dataStack.addStorage(
SQLiteStore(
fileName: "MigrationDemo.sqlite",
migrationMappingProviders: [
CustomSchemaMappingProvider(
from: "MigrationDemoV3",
to: "MigrationDemoV2",
entityMappings: [
.transformEntity(
sourceEntity: "Organism",
destinationEntity: "Organism",
transformer: { (source, createDestination) in
let destination = createDestination()
destination.enumerateAttributes { (attribute, sourceAttribute) in
if let sourceAttribute = sourceAttribute {
destination[attribute] = source[sourceAttribute]
}
}
destination["numberOfFlippers"] = source["numberOfLimbs"]
}
)
]
)
]
),
completion: { [weak self] (result) -> Void in
guard let `self` = self else {
return
}
guard case .success = result else {
self.setEnabled(true)
return
}
self.set(dataStack: dataStack, model: model, scrollToSelection: true)
let count = try! dataStack.queryValue(
From<NSManagedObject>(model.entityType)
.select(Int.self, .count(#keyPath(OrganismV1.dna))))!
if count > 0 {
self.setEnabled(true)
}
else {
for i: Int64 in 0 ..< 20 {
dataStack.perform(
asynchronous: { (transaction) in
for j: Int64 in 0 ..< 500 {
let organism = transaction.create(Into(model.entityType)) as! OrganismProtocol
organism.dna = (i * 500) + j + 1
organism.mutate()
}
},
completion: { _ in }
)
}
dataStack.perform(
asynchronous: { _ in },
completion: { [weak self] _ in
self?.setEnabled(true)
}
)
}
}
)
if let progress = progress {
progress.setProgressHandler { [weak self] (progress) -> Void in
self?.reloadTableHeaderWithProgress(progress)
}
}
}
private func setEnabled(_ enabled: Bool) {
UIView.animate(
withDuration: 0.2,
delay: 0,
options: .beginFromCurrentState,
animations: { () -> Void in
let navigationItem = self.navigationItem
navigationItem.leftBarButtonItem?.isEnabled = enabled
navigationItem.rightBarButtonItem?.isEnabled = enabled
navigationItem.hidesBackButton = !enabled
self.segmentedControl?.isEnabled = enabled
if let tableView = self.tableView {
tableView.alpha = enabled ? 1.0 : 0.5
tableView.isUserInteractionEnabled = enabled
}
},
completion: nil
)
}
private func set(dataStack: DataStack?, model: ModelMetadata?, scrollToSelection: Bool) {
if let dataStack = dataStack, let model = model {
self.segmentedControl?.selectedSegmentIndex = self.models
.firstIndex(
where: { (arg) -> Bool in
let (_, _, schemaHistory) = arg
return schemaHistory.currentModelVersion == model.schemaHistory.currentModelVersion
}
)!
self._dataStack = dataStack
let listMonitor = dataStack.monitorList(
From(model.entityType),
OrderBy<NSManagedObject>(.descending(#keyPath(OrganismV1.dna)))
)
listMonitor.addObserver(self)
self._listMonitor = listMonitor
if self.lastSelectedIndexPath == nil {
if listMonitor.numberOfObjects(in: 0) > 0 {
self.setSelectedIndexPath(IndexPath(row: 0, section: 0), scrollToSelection: true)
}
}
}
else {
self.segmentedControl?.selectedSegmentIndex = UISegmentedControl.noSegment
self._listMonitor = nil
self._dataStack = nil
}
self.updateDisplay(reloadData: true, scrollToSelection: scrollToSelection, animated: false)
}
private func reloadTableHeaderWithProgress(_ progress: Progress) {
self.progressView?.setProgress(Float(progress.fractionCompleted), animated: true)
self.titleLabel?.text = "Migrating: \(progress.localizedDescription ?? "")"
self.organismLabel?.text = "Progressive step \(progress.localizedAdditionalDescription ?? "")"
}
private func updateDisplay(reloadData: Bool, scrollToSelection: Bool, animated: Bool) {
var lines = [String]()
var organismType = ""
if let indexPath = self.lastSelectedIndexPath, let organism = self.listMonitor?[indexPath] {
for property in organism.entity.properties {
let value = organism.value(forKey: property.name) ?? NSNull()
lines.append("\(property.name): \(value)")
}
organismType = organism.entity.managedObjectClassName
}
self.titleLabel?.text = organismType
self.organismLabel?.text = lines.joined(separator: "\n")
self.progressView?.progress = 0
self.headerContainer?.setNeedsLayout()
guard let tableView = self.tableView else {
return
}
if reloadData {
tableView.reloadData()
}
tableView.layoutIfNeeded()
if let indexPath = self.lastSelectedIndexPath,
indexPath.row < tableView.numberOfRows(inSection: 0) {
tableView.selectRow(at: indexPath,
animated: scrollToSelection && animated,
scrollPosition: scrollToSelection ? .middle : .none
)
}
}
}

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
</plist>

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="8166.2" systemVersion="14E46" minimumToolsVersion="Xcode 7.0">
<elements/>
</model>

View File

@@ -1,16 +0,0 @@
//
// OrganismProtocol.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/27.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import Foundation
protocol OrganismProtocol: AnyObject {
var dna: Int64 { get set }
func mutate()
}

View File

@@ -1,22 +0,0 @@
//
// OrganismTableViewCell.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/07/12.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import UIKit
class OrganismTableViewCell: UITableViewCell {
@IBOutlet weak dynamic var dnaLabel: UILabel?
@IBOutlet weak dynamic var mutateButton: UIButton?
var mutateButtonHandler: (() -> Void)?
@IBAction dynamic func mutateButtonTouchUpInside(_ sender: UIButton?) {
self.mutateButtonHandler?()
}
}

View File

@@ -1,25 +0,0 @@
//
// OrganismV1.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/21.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import Foundation
import CoreData
class OrganismV1: NSManagedObject, OrganismProtocol {
@NSManaged var dna: Int64
@NSManaged var hasHead: Bool
@NSManaged var hasTail: Bool
// MARK: OrganismProtocol
func mutate() {
self.hasHead = arc4random_uniform(2) == 1
self.hasTail = arc4random_uniform(2) == 1
}
}

View File

@@ -1,27 +0,0 @@
//
// OrganismV2.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/21.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import Foundation
import CoreData
class OrganismV2: NSManagedObject, OrganismProtocol {
@NSManaged var dna: Int64
@NSManaged var hasHead: Bool
@NSManaged var hasTail: Bool
@NSManaged var numberOfFlippers: Int32
// MARK: OrganismProtocol
func mutate() {
self.hasHead = arc4random_uniform(2) == 1
self.hasTail = arc4random_uniform(2) == 1
self.numberOfFlippers = Int32(arc4random_uniform(9) / 2 * 2)
}
}

File diff suppressed because one or more lines are too long

View File

@@ -1,29 +0,0 @@
//
// OrganismV2ToV3MigrationPolicy.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/27.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import CoreData
class OrganismV2ToV3MigrationPolicy: NSEntityMigrationPolicy {
override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
try super.createDestinationInstances(forSource: sInstance, in: mapping, manager: manager)
for dInstance in manager.destinationInstances(forEntityMappingName: mapping.name, sourceInstances: [sInstance]) {
dInstance.setValue(
false,
forKey: #keyPath(OrganismV3.hasVertebrae)
)
dInstance.setValue(
sInstance.value(forKey: #keyPath(OrganismV2.numberOfFlippers)),
forKey: #keyPath(OrganismV3.numberOfLimbs)
)
}
}
}

View File

@@ -1,29 +0,0 @@
//
// OrganismV3.swift
// LegacyDemo
//
// Created by John Rommel Estropia on 2015/06/27.
// Copyright © 2018 John Rommel Estropia. All rights reserved.
//
import Foundation
import CoreData
class OrganismV3: NSManagedObject, OrganismProtocol {
@NSManaged var dna: Int64
@NSManaged var hasHead: Bool
@NSManaged var hasTail: Bool
@NSManaged var numberOfLimbs: Int32
@NSManaged var hasVertebrae: Bool
// MARK: OrganismProtocol
func mutate() {
self.hasHead = arc4random_uniform(2) == 1
self.hasTail = arc4random_uniform(2) == 1
self.numberOfLimbs = Int32(arc4random_uniform(9) / 2 * 2)
self.hasVertebrae = arc4random_uniform(2) == 1
}
}

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>MigrationDemoV3.xcdatamodel</string>
</dict>
</plist>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="11198.3" systemVersion="15F34" minimumToolsVersion="Xcode 4.3" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Organism" representedClassName="LegacyDemo.OrganismV1" syncable="YES">
<attribute name="dna" optional="YES" attributeType="Integer 64" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasHead" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
<attribute name="hasTail" optional="YES" attributeType="Boolean" usesScalarValueType="NO" syncable="YES"/>
</entity>
<elements>
<element name="Organism" positionX="-36" positionY="9" width="128" height="90"/>
</elements>
</model>

Some files were not shown because too many files have changed in this diff Show More