Skip to content

Commit 9faac23

Browse files
Merge pull request #132 from woocommerce/issue/124-results-controller
Implements ResultsController
2 parents d9927e9 + 48cfaf8 commit 9faac23

File tree

12 files changed

+534
-24
lines changed

12 files changed

+534
-24
lines changed

Storage/Storage.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
B505F6DB20BEEA3200BB1B69 /* Account+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = B505F6D920BEEA3200BB1B69 /* Account+CoreDataClass.swift */; };
1414
B505F6DE20BEEA4F00BB1B69 /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B505F6DD20BEEA4F00BB1B69 /* CoreDataManager.swift */; };
1515
B505F6E020BEEA8100BB1B69 /* StorageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B505F6DF20BEEA8100BB1B69 /* StorageType.swift */; };
16-
B52B0F7920AA287C00477698 /* StorageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52B0F7820AA287C00477698 /* StorageManager.swift */; };
16+
B52B0F7920AA287C00477698 /* StorageManagerType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52B0F7820AA287C00477698 /* StorageManagerType.swift */; };
1717
B52B0F7B20AA28A800477698 /* Object.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52B0F7A20AA28A800477698 /* Object.swift */; };
1818
B54CA5A320A4BBA600F38CD1 /* Storage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B54CA59920A4BBA500F38CD1 /* Storage.framework */; };
1919
B54CA5AA20A4BBA600F38CD1 /* Storage.h in Headers */ = {isa = PBXBuildFile; fileRef = B54CA59C20A4BBA500F38CD1 /* Storage.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -49,7 +49,7 @@
4949
B505F6D920BEEA3200BB1B69 /* Account+CoreDataClass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Account+CoreDataClass.swift"; sourceTree = "<group>"; };
5050
B505F6DD20BEEA4F00BB1B69 /* CoreDataManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataManager.swift; sourceTree = "<group>"; };
5151
B505F6DF20BEEA8100BB1B69 /* StorageType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StorageType.swift; sourceTree = "<group>"; };
52-
B52B0F7820AA287C00477698 /* StorageManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageManager.swift; sourceTree = "<group>"; };
52+
B52B0F7820AA287C00477698 /* StorageManagerType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageManagerType.swift; sourceTree = "<group>"; };
5353
B52B0F7A20AA28A800477698 /* Object.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Object.swift; sourceTree = "<group>"; };
5454
B54CA59920A4BBA500F38CD1 /* Storage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Storage.framework; sourceTree = BUILT_PRODUCTS_DIR; };
5555
B54CA59C20A4BBA500F38CD1 /* Storage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Storage.h; sourceTree = "<group>"; };
@@ -115,7 +115,7 @@
115115
isa = PBXGroup;
116116
children = (
117117
B52B0F7A20AA28A800477698 /* Object.swift */,
118-
B52B0F7820AA287C00477698 /* StorageManager.swift */,
118+
B52B0F7820AA287C00477698 /* StorageManagerType.swift */,
119119
B505F6DF20BEEA8100BB1B69 /* StorageType.swift */,
120120
);
121121
path = Protocols;
@@ -396,7 +396,7 @@
396396
B505F6DB20BEEA3200BB1B69 /* Account+CoreDataClass.swift in Sources */,
397397
B54CA5BD20A4BD3B00F38CD1 /* NSManagedObjectContext+Storage.swift in Sources */,
398398
B59E11DA20A9D00C004121A4 /* WooCommerce.xcdatamodeld in Sources */,
399-
B52B0F7920AA287C00477698 /* StorageManager.swift in Sources */,
399+
B52B0F7920AA287C00477698 /* StorageManagerType.swift in Sources */,
400400
B505F6E020BEEA8100BB1B69 /* StorageType.swift in Sources */,
401401
B54CA5C920A4C17800F38CD1 /* NSObject+Storage.swift in Sources */,
402402
B505F6DA20BEEA3200BB1B69 /* Account+CoreDataProperties.swift in Sources */,

Storage/Storage/CoreData/CoreDataManager.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import CoreData
44

55
/// CoreDataManager: Manages the entire CoreData Stack. Conforms to the StorageManager API.
66
///
7-
public class CoreDataManager: StorageManager {
7+
public class CoreDataManager: StorageManagerType {
88

99
/// Storage Identifier.
1010
///

Storage/Storage/Protocols/StorageManager.swift renamed to Storage/Storage/Protocols/StorageManagerType.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Foundation
33

44
/// Defines the methods and properties implemented by any concrete StorageManager implementation.
55
///
6-
public protocol StorageManager {
6+
public protocol StorageManagerType {
77

88
/// Returns the `Storage` associated to the main thread.
99
///

Yosemite/Yosemite.xcodeproj/project.pbxproj

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
74A7689220D47F9E00F9D437 /* orders.json in Resources */ = {isa = PBXBuildFile; fileRef = 74A7689120D47F9E00F9D437 /* orders.json */; };
1717
B53D89E520E6C22B00F90866 /* Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = B53D89E420E6C22B00F90866 /* Model.swift */; };
1818
B546CCF22093636A007CDA5F /* Yosemite.h in Headers */ = {isa = PBXBuildFile; fileRef = B546CCF12093636A007CDA5F /* Yosemite.h */; settings = {ATTRIBUTES = (Public, ); }; };
19-
B57A133220D2C787003D88DF /* StorageAccount+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B57A133120D2C787003D88DF /* StorageAccount+Extensions.swift */; };
19+
B56C1EBE20EABD2B00D749F9 /* ResultsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56C1EBD20EABD2B00D749F9 /* ResultsController.swift */; };
20+
B56C1EC220EAE2E500D749F9 /* ReadOnlyConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56C1EC120EAE2E500D749F9 /* ReadOnlyConvertible.swift */; };
21+
B57A133220D2C787003D88DF /* Account+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B57A133120D2C787003D88DF /* Account+Extensions.swift */; };
2022
B5A01CA120D19C4700E3207E /* MockupStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A01CA020D19C4700E3207E /* MockupStorage.swift */; };
2123
B5B19DE020E6A45900899568 /* Storage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5B19DDF20E6A45900899568 /* Storage.framework */; };
2224
B5B19DE220E6A45E00899568 /* Networking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5B19DE120E6A45E00899568 /* Networking.framework */; };
@@ -35,6 +37,8 @@
3537
B5C9DE272087FF20006B910A /* MockupAcount.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C9DE202087FF20006B910A /* MockupAcount.swift */; };
3638
B5C9DE282087FF20006B910A /* MockupSite.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C9DE212087FF20006B910A /* MockupSite.swift */; };
3739
B5DC3CB120D1B8720063AC41 /* AccountAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5DC3CB020D1B8720063AC41 /* AccountAction.swift */; };
40+
B5F2AE9520EBAD6000FEDC59 /* ResultsControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F2AE9420EBAD6000FEDC59 /* ResultsControllerTests.swift */; };
41+
B5F2AE9720EBB54A00FEDC59 /* FetchedResultsControllerDelegateWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F2AE9620EBB54A00FEDC59 /* FetchedResultsControllerDelegateWrapper.swift */; };
3842
/* End PBXBuildFile section */
3943

4044
/* Begin PBXContainerItemProxy section */
@@ -61,7 +65,9 @@
6165
ABE0D84C5393D9EE2CCF2B7E /* Pods-YosemiteTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-YosemiteTests.release.xcconfig"; path = "../Pods/Target Support Files/Pods-YosemiteTests/Pods-YosemiteTests.release.xcconfig"; sourceTree = "<group>"; };
6266
B53D89E420E6C22B00F90866 /* Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Model.swift; path = Yosemite/Model/Model.swift; sourceTree = SOURCE_ROOT; };
6367
B546CCF12093636A007CDA5F /* Yosemite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Yosemite.h; sourceTree = "<group>"; };
64-
B57A133120D2C787003D88DF /* StorageAccount+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StorageAccount+Extensions.swift"; sourceTree = "<group>"; };
68+
B56C1EBD20EABD2B00D749F9 /* ResultsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultsController.swift; sourceTree = "<group>"; };
69+
B56C1EC120EAE2E500D749F9 /* ReadOnlyConvertible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadOnlyConvertible.swift; sourceTree = "<group>"; };
70+
B57A133120D2C787003D88DF /* Account+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Account+Extensions.swift"; sourceTree = "<group>"; };
6571
B5A01CA020D19C4700E3207E /* MockupStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockupStorage.swift; sourceTree = "<group>"; };
6672
B5B19DDF20E6A45900899568 /* Storage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Storage.framework; sourceTree = BUILT_PRODUCTS_DIR; };
6773
B5B19DE120E6A45E00899568 /* Networking.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Networking.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -83,6 +89,8 @@
8389
B5C9DE202087FF20006B910A /* MockupAcount.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockupAcount.swift; sourceTree = "<group>"; };
8490
B5C9DE212087FF20006B910A /* MockupSite.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockupSite.swift; sourceTree = "<group>"; };
8591
B5DC3CB020D1B8720063AC41 /* AccountAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountAction.swift; sourceTree = "<group>"; };
92+
B5F2AE9420EBAD6000FEDC59 /* ResultsControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultsControllerTests.swift; sourceTree = "<group>"; };
93+
B5F2AE9620EBB54A00FEDC59 /* FetchedResultsControllerDelegateWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FetchedResultsControllerDelegateWrapper.swift; sourceTree = "<group>"; };
8694
C25501C7F936D2FD32FAF3F4 /* Pods_Yosemite.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Yosemite.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8795
/* End PBXFileReference section */
8896

@@ -113,16 +121,19 @@
113121
isa = PBXGroup;
114122
children = (
115123
B53D89E420E6C22B00F90866 /* Model.swift */,
124+
B57A133120D2C787003D88DF /* Account+Extensions.swift */,
116125
);
117126
path = Model;
118127
sourceTree = "<group>";
119128
};
120-
B57A133020D2C770003D88DF /* Extensions */ = {
129+
B56C1EBC20EABD1C00D749F9 /* Tools */ = {
121130
isa = PBXGroup;
122131
children = (
123-
B57A133120D2C787003D88DF /* StorageAccount+Extensions.swift */,
132+
B56C1EBD20EABD2B00D749F9 /* ResultsController.swift */,
133+
B56C1EC120EAE2E500D749F9 /* ReadOnlyConvertible.swift */,
134+
B5F2AE9620EBB54A00FEDC59 /* FetchedResultsControllerDelegateWrapper.swift */,
124135
);
125-
path = Extensions;
136+
path = Tools;
126137
sourceTree = "<group>";
127138
};
128139
B5BC736320D1A98500B5B6FA /* Stores */ = {
@@ -198,10 +209,10 @@
198209
children = (
199210
B5C9DE132087FF0E006B910A /* Internal */,
200211
B5C9DE0F2087FF0E006B910A /* Base */,
201-
B57A133020D2C770003D88DF /* Extensions */,
202212
B5DC3CAF20D1B8660063AC41 /* Actions */,
203213
B5BC736320D1A98500B5B6FA /* Stores */,
204214
B53D89E720E6C7DC00F90866 /* Model */,
215+
B56C1EBC20EABD1C00D749F9 /* Tools */,
205216
B546CCF12093636A007CDA5F /* Yosemite.h */,
206217
B5C9DDF92087FEC0006B910A /* Info.plist */,
207218
);
@@ -216,6 +227,7 @@
216227
B5C9DE1D2087FF20006B910A /* Mockups */,
217228
B5C9DE192087FF20006B910A /* Base */,
218229
B5BC736620D1AA8F00B5B6FA /* Stores */,
230+
B5F2AE9320EBAD5200FEDC59 /* Tools */,
219231
B5C9DE052087FEC0006B910A /* Info.plist */,
220232
);
221233
path = YosemiteTests;
@@ -268,6 +280,14 @@
268280
path = Actions;
269281
sourceTree = "<group>";
270282
};
283+
B5F2AE9320EBAD5200FEDC59 /* Tools */ = {
284+
isa = PBXGroup;
285+
children = (
286+
B5F2AE9420EBAD6000FEDC59 /* ResultsControllerTests.swift */,
287+
);
288+
path = Tools;
289+
sourceTree = "<group>";
290+
};
271291
E35A5B190486BCE158B0320B /* Pods */ = {
272292
isa = PBXGroup;
273293
children = (
@@ -455,13 +475,16 @@
455475
B5C9DE152087FF0E006B910A /* Dispatcher.swift in Sources */,
456476
B5DC3CB120D1B8720063AC41 /* AccountAction.swift in Sources */,
457477
B5BC736520D1A98500B5B6FA /* AccountStore.swift in Sources */,
478+
B56C1EC220EAE2E500D749F9 /* ReadOnlyConvertible.swift in Sources */,
458479
B5B5C797208E49B600642956 /* Action+Internal.swift in Sources */,
459480
74A7688C20D45EBA00F9D437 /* OrderStore.swift in Sources */,
460481
B53D89E520E6C22B00F90866 /* Model.swift in Sources */,
461482
74A7689020D45F9300F9D437 /* OrderAction.swift in Sources */,
462483
B5C9DE182087FF0E006B910A /* Assert.swift in Sources */,
463484
B5C9DE162087FF0E006B910A /* Store.swift in Sources */,
464-
B57A133220D2C787003D88DF /* StorageAccount+Extensions.swift in Sources */,
485+
B56C1EBE20EABD2B00D749F9 /* ResultsController.swift in Sources */,
486+
B5F2AE9720EBB54A00FEDC59 /* FetchedResultsControllerDelegateWrapper.swift in Sources */,
487+
B57A133220D2C787003D88DF /* Account+Extensions.swift in Sources */,
465488
);
466489
runOnlyForDeploymentPostprocessing = 0;
467490
};
@@ -477,6 +500,7 @@
477500
B5C9DE252087FF20006B910A /* MockupProcessor.swift in Sources */,
478501
B5C9DE282087FF20006B910A /* MockupSite.swift in Sources */,
479502
B5BC736820D1AA8F00B5B6FA /* AccountStoreTests.swift in Sources */,
503+
B5F2AE9520EBAD6000FEDC59 /* ResultsControllerTests.swift in Sources */,
480504
B5BC736E20D1AB3600B5B6FA /* Constants.swift in Sources */,
481505
);
482506
runOnlyForDeploymentPostprocessing = 0;

Yosemite/Yosemite/Base/Store.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ open class Store: ActionsProcessor {
1515

1616
/// Storage Layer
1717
///
18-
public let storageManager: StorageManager
18+
public let storageManager: StorageManagerType
1919

2020
/// Network Layer
2121
///
@@ -29,7 +29,7 @@ open class Store: ActionsProcessor {
2929
/// - storageManager: Storage Provider to be used in all of the current Store OP's.
3030
/// - network: Network that should be used, when it comes to building a Remote.
3131
///
32-
public init(dispatcher: Dispatcher, storageManager: StorageManager, network: Network) {
32+
public init(dispatcher: Dispatcher, storageManager: StorageManagerType, network: Network) {
3333
self.dispatcher = dispatcher
3434
self.storageManager = storageManager
3535
self.network = network

Yosemite/Yosemite/Extensions/StorageAccount+Extensions.swift renamed to Yosemite/Yosemite/Model/Account+Extensions.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,23 @@ import Storage
33
import Networking
44

55

6-
/// Storage.Account Convenience Methods.
7-
///
8-
extension Storage.Account {
6+
// MARK: - Storage.Account: ReadOnlyConvertible
7+
//
8+
extension Storage.Account: ReadOnlyConvertible {
99

10-
/// Updates the Storage.Account with the Networking.Account's Payload.
10+
/// Updates the Storage.Account with the a ReadOnly.
1111
///
12-
func update(with account: Networking.Account) {
12+
public func update(with account: Yosemite.Account) {
1313
displayName = account.displayName
1414
email = account.email
1515
gravatarUrl = account.gravatarUrl
1616
userID = Int64(account.userID)
1717
username = account.username
1818
}
1919

20-
/// Returns an immutable version of the receiver.
20+
/// Returns a ReadOnly version of the receiver.
2121
///
22-
func toStruct() -> Networking.Account {
22+
public func toReadOnly() -> Yosemite.Account {
2323
return Account(userID: Int(userID),
2424
displayName: displayName ?? "",
2525
email: email ?? "",

Yosemite/Yosemite/Stores/AccountStore.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ extension AccountStore {
5555
/// Retrieves the account associated with a given User ID (if any!).
5656
///
5757
func retrieveAccount(userId: Int, onCompletion: (Account?) -> Void) {
58-
let account = loadStoredAccount(userId: userId)?.toStruct()
58+
let account = loadStoredAccount(userId: userId)?.toReadOnly()
5959
onCompletion(account)
6060
}
6161
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import Foundation
2+
import CoreData
3+
4+
5+
// MARK: - FetchedResultsControllerDelegateWrapper
6+
//
7+
class FetchedResultsControllerDelegateWrapper: NSObject {
8+
9+
/// Relays FRC's Delegate: `controllerWillChangeContent`
10+
///
11+
var onWillChangeContent: (() -> Void)?
12+
13+
/// Relays FRC's Delegate: `controllerDidChangeContent`
14+
///
15+
var onDidChangeContent: (() -> Void)?
16+
17+
/// Relays FRC's Delegate: `didChange anObject`
18+
///
19+
var onDidChangeObject: ((_ object: Any, _ indexPath: IndexPath?, _ type: NSFetchedResultsChangeType, _ newIndexPath: IndexPath?) -> Void)?
20+
21+
/// Relays FRC's Delegate: `didChange sectionInfo`
22+
///
23+
var onDidChangeSection: ((_ sectionInfo: NSFetchedResultsSectionInfo, _ sectionIndex: Int, _ type: NSFetchedResultsChangeType) -> Void)?
24+
}
25+
26+
27+
28+
// MARK: - NSFetchedResultsControllerDelegate Conformance
29+
//
30+
extension FetchedResultsControllerDelegateWrapper: NSFetchedResultsControllerDelegate {
31+
32+
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
33+
onWillChangeContent?()
34+
}
35+
36+
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
37+
onDidChangeContent?()
38+
}
39+
40+
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
41+
onDidChangeObject?(anObject, indexPath, type, newIndexPath)
42+
}
43+
44+
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
45+
onDidChangeSection?(sectionInfo, sectionIndex, type)
46+
}
47+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import Foundation
2+
import Storage
3+
4+
5+
// MARK: - Represents a Mutable Entity that can be converted into a ReadOnly Type.
6+
//
7+
public protocol ReadOnlyConvertible: class {
8+
9+
/// Represents the ReadOnly Type (mirroring the receiver).
10+
///
11+
associatedtype ReadOnlyType
12+
13+
/// Updates the Receiver with the ReadOnly Instance.
14+
///
15+
func update(with entity: ReadOnlyType)
16+
17+
/// Returns a ReadOnly version of the receiver.
18+
///
19+
func toReadOnly() -> ReadOnlyType
20+
}

0 commit comments

Comments
 (0)