Skip to content

Commit a8ea09e

Browse files
committed
Revert "Restore results controller and add transformed options"
This reverts commit 7e65cbb.
1 parent 7c63a33 commit a8ea09e

File tree

3 files changed

+86
-54
lines changed

3 files changed

+86
-54
lines changed

Modules/Sources/Yosemite/Tools/ResultsController.swift

Lines changed: 74 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ import Foundation
22
import Storage
33
import CoreData
44

5+
6+
57
// MARK: - MutableType: Storage.framework Type that will be retrieved (and converted into ReadOnly)
68
//
79
public typealias ResultsControllerMutableType = NSManagedObject & ReadOnlyConvertible
810

911

10-
// MARK: - ResultsController
12+
// MARK: - GenericResultsController (Core Implementation)
1113
//
12-
public class ResultsController<T: ResultsControllerMutableType> {
14+
public class GenericResultsController<T: ResultsControllerMutableType, Output> {
1315

1416
/// The `StorageType` used to fetch objects.
1517
///
@@ -77,7 +79,7 @@ public class ResultsController<T: ResultsControllerMutableType> {
7779

7880
/// Closure to be executed whenever an Object is updated.
7981
///
80-
public var onDidChangeObject: ((_ object: T.ReadOnlyType, _ indexPath: IndexPath?, _ type: ChangeType, _ newIndexPath: IndexPath?) -> Void)?
82+
public var onDidChangeObject: ((_ object: Output, _ indexPath: IndexPath?, _ type: ChangeType, _ newIndexPath: IndexPath?) -> Void)?
8183

8284
/// Closure to be executed whenever an entire Section is updated.
8385
///
@@ -92,19 +94,25 @@ public class ResultsController<T: ResultsControllerMutableType> {
9294
///
9395
private let fetchLimit: Int?
9496

97+
/// Transformer closure to convert T to Output type.
98+
///
99+
private let transformer: (T) -> Output
100+
95101
/// Designated Initializer.
96102
///
97103
public init(viewStorage: StorageType,
98104
sectionNameKeyPath: String? = nil,
99105
matching predicate: NSPredicate? = nil,
100106
fetchLimit: Int? = nil,
101-
sortedBy descriptors: [NSSortDescriptor]) {
107+
sortedBy descriptors: [NSSortDescriptor],
108+
transformer: @escaping (T) -> Output) {
102109

103110
self.viewStorage = viewStorage
104111
self.sectionNameKeyPath = sectionNameKeyPath
105112
self.predicate = predicate
106113
self.fetchLimit = fetchLimit
107114
self.sortDescriptors = descriptors
115+
self.transformer = transformer
108116

109117
setupResultsController()
110118
setupEventsForwarding()
@@ -117,13 +125,15 @@ public class ResultsController<T: ResultsControllerMutableType> {
117125
sectionNameKeyPath: String? = nil,
118126
matching predicate: NSPredicate? = nil,
119127
fetchLimit: Int? = nil,
120-
sortedBy descriptors: [NSSortDescriptor]) {
128+
sortedBy descriptors: [NSSortDescriptor],
129+
transformer: @escaping (T) -> Output) {
121130

122131
self.init(viewStorage: storageManager.viewStorage,
123132
sectionNameKeyPath: sectionNameKeyPath,
124133
matching: predicate,
125134
fetchLimit: fetchLimit,
126-
sortedBy: descriptors)
135+
sortedBy: descriptors,
136+
transformer: transformer)
127137
}
128138

129139

@@ -137,14 +147,14 @@ public class ResultsController<T: ResultsControllerMutableType> {
137147
///
138148
/// Prefer to use `safeObject(at:)` instead.
139149
///
140-
public func object(at indexPath: IndexPath) -> T.ReadOnlyType {
141-
return controller.object(at: indexPath).toReadOnly()
150+
public func object(at indexPath: IndexPath) -> Output {
151+
return transformer(controller.object(at: indexPath))
142152
}
143153

144154
/// Returns the fetched object at the given `indexPath`. Returns `nil` if the `indexPath`
145155
/// does not exist.
146156
///
147-
public func safeObject(at indexPath: IndexPath) -> T.ReadOnlyType? {
157+
public func safeObject(at indexPath: IndexPath) -> Output? {
148158
guard !isEmpty else {
149159
return nil
150160
}
@@ -158,7 +168,7 @@ public class ResultsController<T: ResultsControllerMutableType> {
158168
return nil
159169
}
160170

161-
return controller.object(at: indexPath).toReadOnly()
171+
return transformer(controller.object(at: indexPath))
162172
}
163173

164174
/// Returns the Plain ObjectIndex corresponding to a given IndexPath. You can use this index to map the
@@ -179,21 +189,6 @@ public class ResultsController<T: ResultsControllerMutableType> {
179189
return output
180190
}
181191

182-
/// Returns an array of all of the transformed fetched objects.
183-
/// Note: Avoid calling this in computed variables as the conversion of storage items can be costly.
184-
///
185-
public func transformedObjects<U>(using transformation: (T) -> U) -> [U] {
186-
controller.fetchedObjects?.compactMap { mutableObject in
187-
transformation(mutableObject)
188-
} ?? []
189-
}
190-
191-
/// Returns a transformed object at a given index
192-
///
193-
public func transformedObject<U>(at indexPath: IndexPath, using transformation: (T) -> U) -> U {
194-
transformation(controller.object(at: indexPath))
195-
}
196-
197192
/// Indicates if there are any Objects matching the specified criteria.
198193
///
199194
public var isEmpty: Bool {
@@ -209,22 +204,22 @@ public class ResultsController<T: ResultsControllerMutableType> {
209204
/// Returns an array of all of the (ReadOnly) Fetched Objects.
210205
/// Note: Avoid calling this in computed variables as the conversion of storage items can be costly.
211206
///
212-
public var fetchedObjects: [T.ReadOnlyType] {
213-
let readOnlyObjects = controller.fetchedObjects?.compactMap { mutableObject in
214-
mutableObject.toReadOnly()
207+
public var fetchedObjects: [Output] {
208+
let transformedObjects = controller.fetchedObjects?.compactMap { mutableObject in
209+
transformer(mutableObject)
215210
}
216211

217-
return readOnlyObjects ?? []
212+
return transformedObjects ?? []
218213
}
219214

220215
/// Returns an array of SectionInfo Entitites.
221216
///
222217
public var sections: [SectionInfo] {
223-
let readOnlySections = controller.sections?.compactMap { mutableSection in
224-
SectionInfo(mutableSection: mutableSection)
218+
let transformedSections = controller.sections?.compactMap { mutableSection in
219+
SectionInfo(mutableSection: mutableSection, transformer: transformer)
225220
}
226221

227-
return readOnlySections ?? []
222+
return transformedSections ?? []
228223
}
229224

230225
/// Returns an optional index path of the first matching object.
@@ -274,17 +269,17 @@ public class ResultsController<T: ResultsControllerMutableType> {
274269
return
275270
}
276271

277-
let readOnlyObject = object.toReadOnly()
278-
self.onDidChangeObject?(readOnlyObject, indexPath, type, newIndexPath)
272+
let transformedObject = transformer(object)
273+
self.onDidChangeObject?(transformedObject, indexPath, type, newIndexPath)
279274
}
280275

281276
internalDelegate.onDidChangeSection = { [weak self] (mutableSection, sectionIndex, type) in
282277
guard let `self` = self else {
283278
return
284279
}
285280

286-
let readOnlySection = SectionInfo(mutableSection: mutableSection)
287-
self.onDidChangeSection?(readOnlySection, sectionIndex, type)
281+
let transformedSection = SectionInfo(mutableSection: mutableSection, transformer: transformer)
282+
self.onDidChangeSection?(transformedSection, sectionIndex, type)
288283
}
289284
}
290285

@@ -308,7 +303,7 @@ public class ResultsController<T: ResultsControllerMutableType> {
308303

309304
// MARK: - Nested Types
310305
//
311-
public extension ResultsController {
306+
public extension GenericResultsController {
312307

313308
// MARK: - ResultsController.ChangeType
314309
//
@@ -336,9 +331,13 @@ public extension ResultsController {
336331
mutableSectionInfo.numberOfObjects
337332
}
338333

339-
/// Returns the array of (ReadOnly) objects in the section.
334+
/// Transformer closure to convert objects in the section.
335+
///
336+
private let transformer: (T) -> Output
337+
338+
/// Returns the array of transformed objects in the section.
340339
///
341-
private(set) public lazy var objects: [T.ReadOnlyType] = {
340+
private(set) public lazy var objects: [Output] = {
342341
guard let objects = mutableSectionInfo.objects else {
343342
return []
344343
}
@@ -347,13 +346,47 @@ public extension ResultsController {
347346
return []
348347
}
349348

350-
return castedObjects.map { $0.toReadOnly() }
349+
return castedObjects.map { transformer($0) }
351350
}()
352351

353352
/// Designated Initializer
354353
///
355-
init(mutableSection: NSFetchedResultsSectionInfo) {
354+
init(mutableSection: NSFetchedResultsSectionInfo, transformer: @escaping (T) -> Output) {
356355
mutableSectionInfo = mutableSection
356+
self.transformer = transformer
357357
}
358358
}
359359
}
360+
361+
// MARK: - ResultsController (Backward Compatible Specialization)
362+
//
363+
public class ResultsController<T: ResultsControllerMutableType>: GenericResultsController<T, T.ReadOnlyType> {
364+
/// Designated Initializer.
365+
///
366+
public init(viewStorage: StorageType,
367+
sectionNameKeyPath: String? = nil,
368+
matching predicate: NSPredicate? = nil,
369+
fetchLimit: Int? = nil,
370+
sortedBy descriptors: [NSSortDescriptor]) {
371+
super.init(viewStorage: viewStorage,
372+
sectionNameKeyPath: sectionNameKeyPath,
373+
matching: predicate,
374+
fetchLimit: fetchLimit,
375+
sortedBy: descriptors,
376+
transformer: { $0.toReadOnly() })
377+
}
378+
379+
/// Convenience Initializer.
380+
///
381+
public convenience init(storageManager: StorageManagerType,
382+
sectionNameKeyPath: String? = nil,
383+
matching predicate: NSPredicate? = nil,
384+
fetchLimit: Int? = nil,
385+
sortedBy descriptors: [NSSortDescriptor]) {
386+
self.init(viewStorage: storageManager.viewStorage,
387+
sectionNameKeyPath: sectionNameKeyPath,
388+
matching: predicate,
389+
fetchLimit: fetchLimit,
390+
sortedBy: descriptors)
391+
}
392+
}

WooCommerce/Classes/ViewModels/Order Details/OrderDetailsResultsControllers.swift

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ final class OrderDetailsResultsControllers {
2323

2424
/// Product ResultsController.
2525
///
26-
private lazy var productResultsController: ResultsController<StorageProduct> = createProductResultsController()
26+
private lazy var productResultsController: GenericResultsController<StorageProduct, OrderDetailsProduct> = createProductResultsController()
2727

2828
/// ProductVariation ResultsController.
2929
///
@@ -245,12 +245,9 @@ private extension OrderDetailsResultsControllers {
245245
}
246246

247247
private func configureProductResultsController(onReload: @escaping () -> Void) {
248-
let transformationHandler: (StorageProduct) -> OrderDetailsProduct = {
249-
OrderDetailsProduct(storageProduct: $0)
250-
}
251248
productResultsController.onDidChangeContent = { [weak self] in
252249
guard let self else { return }
253-
products = productResultsController.transformedObjects(using: transformationHandler)
250+
products = productResultsController.fetchedObjects
254251
onReload()
255252
}
256253

@@ -264,7 +261,7 @@ private extension OrderDetailsResultsControllers {
264261

265262
do {
266263
try productResultsController.performFetch()
267-
products = productResultsController.transformedObjects(using: transformationHandler)
264+
products = productResultsController.fetchedObjects
268265
} catch {
269266
DDLogError("⛔️ Unable to fetch Products for Site \(siteID): \(error)")
270267
}
@@ -377,15 +374,16 @@ private extension OrderDetailsResultsControllers {
377374
try? shippingMethodsResultsController.performFetch()
378375
}
379376

380-
func createProductResultsController() -> ResultsController<StorageProduct> {
377+
func createProductResultsController() -> GenericResultsController<StorageProduct, OrderDetailsProduct> {
381378
let productIDs = order.items.map { $0.productID }
382379
let predicate = NSPredicate(format: "siteID == %lld AND productID IN %@", siteID, productIDs)
383380
let descriptor = NSSortDescriptor(key: "name", ascending: true)
384381

385-
return ResultsController<StorageProduct>(
382+
return GenericResultsController<StorageProduct, OrderDetailsProduct>(
386383
storageManager: storageManager,
387384
matching: predicate,
388-
sortedBy: [descriptor]
385+
sortedBy: [descriptor],
386+
transformer: { OrderDetailsProduct(storageProduct: $0) }
389387
)
390388
}
391389
}

WooCommerce/Classes/ViewModels/Order Details/Refund Details/RefundDetailsResultController.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,23 @@ import Yosemite
77
final class RefundDetailsResultController {
88
/// Product ResultsController.
99
///
10-
private lazy var productResultsController: ResultsController<StorageProduct> = {
10+
private lazy var productResultsController: GenericResultsController<StorageProduct, OrderDetailsProduct> = {
1111
let storageManager = ServiceLocator.storageManager
1212
let predicate = NSPredicate(format: "siteID == %lld", siteID)
1313
let descriptor = NSSortDescriptor(key: "name", ascending: true)
1414

15-
return ResultsController<StorageProduct>(
15+
return GenericResultsController<StorageProduct, OrderDetailsProduct>(
1616
storageManager: storageManager,
1717
matching: predicate,
18-
sortedBy: [descriptor]
18+
sortedBy: [descriptor],
19+
transformer: { OrderDetailsProduct(storageProduct: $0) }
1920
)
2021
}()
2122

2223
/// Products from an Order
2324
///
2425
var products: [OrderDetailsProduct] {
25-
productResultsController.transformedObjects(using: { OrderDetailsProduct(storageProduct: $0) })
26+
productResultsController.fetchedObjects
2627
}
2728

2829
private let siteID: Int64

0 commit comments

Comments
 (0)