From 82fe38aa0adeb4c1fbf05a47fd61c4222e094531 Mon Sep 17 00:00:00 2001 From: Huong Do Date: Tue, 24 Jun 2025 16:47:03 +0700 Subject: [PATCH] Revert "Add option to fetch lightweight objects to reduce app hangs (#15774)" This reverts commit 0bebc0555e0063778575da86b65d247d6a6670ad, reversing changes made to b7e7ffdfda7c1edb70bf6e77159420bf5880e7f1. --- .../Storage/Order+ReadOnlyConvertible.swift | 45 ---------- .../Storage/Product+ReadOnlyConvertible.swift | 87 ------------------- .../FetchResultSnapshotsProvider.swift | 10 --- .../Yosemite/Tools/ReadOnlyConvertible.swift | 10 --- .../Yosemite/Tools/ResultsController.swift | 17 ---- RELEASE-NOTES.txt | 1 - .../OrderDetailsResultsControllers.swift | 2 +- .../BlazeCampaignCreationFormViewModel.swift | 2 +- .../Dashboard/DashboardViewModel.swift | 2 +- .../WooShippingItemsDataSource.swift | 2 +- .../Orders/OrderListViewModel.swift | 4 +- .../Products/ProductsViewController.swift | 6 +- 12 files changed, 9 insertions(+), 179 deletions(-) diff --git a/Modules/Sources/Yosemite/Model/Storage/Order+ReadOnlyConvertible.swift b/Modules/Sources/Yosemite/Model/Storage/Order+ReadOnlyConvertible.swift index 5090620f893..7f1338eefde 100644 --- a/Modules/Sources/Yosemite/Model/Storage/Order+ReadOnlyConvertible.swift +++ b/Modules/Sources/Yosemite/Model/Storage/Order+ReadOnlyConvertible.swift @@ -123,51 +123,6 @@ extension Storage.Order: ReadOnlyConvertible { } - /// Returns a lightweight ReadOnly version of the receiver without any relationships populated. - /// - public func toLightweightReadOnly() -> Yosemite.Order { - Order(siteID: siteID, - orderID: orderID, - parentID: parentID, - customerID: customerID, - orderKey: orderKey, - isEditable: isEditable, - needsPayment: needsPayment, - needsProcessing: needsPayment, - number: number ?? "", - status: OrderStatusEnum(rawValue: statusKey), - currency: currency ?? "", - currencySymbol: "", // Not stored in the Storage Layer, only used in the notifications extension. - customerNote: customerNote ?? "", - dateCreated: dateCreated ?? Date(), - dateModified: dateModified ?? Date(), - datePaid: datePaid, - discountTotal: discountTotal ?? "", - discountTax: discountTax ?? "", - shippingTotal: shippingTotal ?? "", - shippingTax: shippingTax ?? "", - total: total ?? "", - totalTax: totalTax ?? "", - paymentMethodID: paymentMethodID ?? "", - paymentMethodTitle: paymentMethodTitle ?? "", - paymentURL: paymentURL as URL?, - chargeID: chargeID, - items: [], - billingAddress: createReadOnlyBillingAddress(), - shippingAddress: createReadOnlyShippingAddress(), - shippingLines: [], - coupons: [], - refunds: [], - fees: [], - taxes: [], - customFields: [], - renewalSubscriptionID: renewalSubscriptionID, - appliedGiftCards: [], - attributionInfo: attributionInfo?.toReadOnly(), - shippingLabels: []) - - } - // MARK: - Private Helpers diff --git a/Modules/Sources/Yosemite/Model/Storage/Product+ReadOnlyConvertible.swift b/Modules/Sources/Yosemite/Model/Storage/Product+ReadOnlyConvertible.swift index 86f91a97ce8..65ddd38c5a9 100644 --- a/Modules/Sources/Yosemite/Model/Storage/Product+ReadOnlyConvertible.swift +++ b/Modules/Sources/Yosemite/Model/Storage/Product+ReadOnlyConvertible.swift @@ -200,93 +200,6 @@ extension Storage.Product: ReadOnlyConvertible { customFields: productCustomFields.sorted { $0.metadataID < $1.metadataID }) } - /// Returns a lightweight ReadOnly version of the receiver. - /// No relationships are populated except for images. - /// - public func toLightweightReadOnly() -> Yosemite.Product { - - let productImages = imagesArray.map { $0.toReadOnly() } - - return Product(siteID: siteID, - productID: productID, - name: name, - slug: slug, - permalink: permalink, - date: date ?? Date(timeIntervalSince1970: 0), - dateCreated: dateCreated ?? Date(timeIntervalSince1970: 0), - dateModified: dateModified, - dateOnSaleStart: dateOnSaleStart, - dateOnSaleEnd: dateOnSaleEnd, - productTypeKey: productTypeKey, - statusKey: statusKey, - featured: featured, - catalogVisibilityKey: catalogVisibilityKey, - fullDescription: fullDescription, - shortDescription: briefDescription, - sku: sku, - globalUniqueID: globalUniqueID, - price: price, - regularPrice: regularPrice, - salePrice: salePrice, - onSale: onSale, - purchasable: purchasable, - totalSales: Int(totalSales), - virtual: virtual, - downloadable: downloadable, - downloads: [], - downloadLimit: downloadLimit, - downloadExpiry: downloadExpiry, - buttonText: buttonText, - externalURL: externalURL, - taxStatusKey: taxStatusKey, - taxClass: taxClass, - manageStock: manageStock, - stockQuantity: nil, - stockStatusKey: stockStatusKey, - backordersKey: backordersKey, - backordersAllowed: backordersAllowed, - backordered: backordered, - soldIndividually: soldIndividually, - weight: weight, - dimensions: createReadOnlyDimensions(), - shippingRequired: shippingRequired, - shippingTaxable: shippingTaxable, - shippingClass: shippingClass, - shippingClassID: shippingClassID, - productShippingClass: nil, - reviewsAllowed: reviewsAllowed, - averageRating: averageRating, - ratingCount: Int(ratingCount), - relatedIDs: convertIDArray(relatedIDs), - upsellIDs: convertIDArray(upsellIDs), - crossSellIDs: convertIDArray(crossSellIDs), - parentID: parentID, - purchaseNote: purchaseNote, - categories: [], - tags: [], - images: productImages, - attributes: [], - defaultAttributes: [], - variations: variations ?? [], - groupedProducts: groupedProducts ?? [], - menuOrder: Int(menuOrder), - addOns: [], - isSampleItem: isSampleItem, - bundleStockStatus: nil, - bundleStockQuantity: bundleStockQuantity as? Int64, - bundleMinSize: bundleMinSize?.decimalValue, - bundleMaxSize: bundleMaxSize?.decimalValue, - bundledItems: [], - password: password, - compositeComponents: [], - subscription: subscription?.toReadOnly(), - minAllowedQuantity: minAllowedQuantity, - maxAllowedQuantity: maxAllowedQuantity, - groupOfQuantity: groupOfQuantity, - combineVariationQuantities: combineVariationQuantities?.boolValue, - customFields: []) - } - // MARK: - Private Helpers private func createReadOnlyDimensions() -> Yosemite.ProductDimensions { diff --git a/Modules/Sources/Yosemite/SnapshotsProvider/FetchResultSnapshotsProvider.swift b/Modules/Sources/Yosemite/SnapshotsProvider/FetchResultSnapshotsProvider.swift index 94fd5126f5d..c3d4dca8b70 100644 --- a/Modules/Sources/Yosemite/SnapshotsProvider/FetchResultSnapshotsProvider.swift +++ b/Modules/Sources/Yosemite/SnapshotsProvider/FetchResultSnapshotsProvider.swift @@ -179,16 +179,6 @@ public final class FetchResultSnapshotsProvider MutableType.ReadOnlyType? { - if let storageOrder = storage.loadObject(ofType: MutableType.self, with: objectID) { - return storageOrder.toLightweightReadOnly() - } else { - return nil - } - } } // MARK: - FetchedResultsController Activation diff --git a/Modules/Sources/Yosemite/Tools/ReadOnlyConvertible.swift b/Modules/Sources/Yosemite/Tools/ReadOnlyConvertible.swift index ab33955ce12..ed088bea7e6 100644 --- a/Modules/Sources/Yosemite/Tools/ReadOnlyConvertible.swift +++ b/Modules/Sources/Yosemite/Tools/ReadOnlyConvertible.swift @@ -17,10 +17,6 @@ public protocol ReadOnlyConvertible: TypeErasedReadOnlyConvertible { /// Returns a ReadOnly version of the receiver. /// func toReadOnly() -> ReadOnlyType - - /// Returns a lightweight ReadOnly version of the receiver. - /// - func toLightweightReadOnly() -> ReadOnlyType } @@ -44,10 +40,4 @@ extension ReadOnlyConvertible { public func toTypeErasedReadOnly() -> Any { return toReadOnly() } - - /// Default implementation is the same result with `toReadOnly()` - /// - public func toLightweightReadOnly() -> ReadOnlyType { - toReadOnly() - } } diff --git a/Modules/Sources/Yosemite/Tools/ResultsController.swift b/Modules/Sources/Yosemite/Tools/ResultsController.swift index a1405e6ae1f..ee9ea7b1992 100644 --- a/Modules/Sources/Yosemite/Tools/ResultsController.swift +++ b/Modules/Sources/Yosemite/Tools/ResultsController.swift @@ -143,12 +143,6 @@ public class ResultsController { return controller.object(at: indexPath).toReadOnly() } - /// Returns the lightweight fetched object at a given indexPath. - /// - public func lightweightObject(at indexPath: IndexPath) -> T.ReadOnlyType { - return controller.object(at: indexPath).toLightweightReadOnly() - } - /// Returns the fetched object at the given `indexPath`. Returns `nil` if the `indexPath` /// does not exist. /// @@ -209,17 +203,6 @@ public class ResultsController { return readOnlyObjects ?? [] } - /// Returns an array of all of the (ReadOnly) Fetched Objects with no relationships populated. - /// Suitable for list views. - /// - public var lightweightFetchedObjects: [T.ReadOnlyType] { - let readOnlyObjects = controller.fetchedObjects?.compactMap { mutableObject in - mutableObject.toLightweightReadOnly() - } - - return readOnlyObjects ?? [] - } - /// Returns an array of SectionInfo Entitites. /// public var sections: [SectionInfo] { diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index f67a0b92f44..c98ec19f5eb 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -5,7 +5,6 @@ ----- - [*] Order Details: Fix crash when reloading data [https://github.com/woocommerce/woocommerce-ios/pull/15764] - [*] Shipping Labels: Improved shipment management UI by hiding remove/merge options instead of disabling them, hiding merge option for orders with 2 or fewer unfulfilled shipments, and hiding the ellipsis menu when no remove/merge actions are available [https://github.com/woocommerce/woocommerce-ios/pull/15760] -- [*] Improve app performance by fetching lightweight objects when necessary [https://github.com/woocommerce/woocommerce-ios/pull/15774] - [**] POS: a POS tab in the tab bar is now available in the app for stores eligible for Point of Sale, instead of the previous entry point in the Menu tab. [https://github.com/woocommerce/woocommerce-ios/pull/15766] - [***] POS: Barcode scanning using Bluetooth scanners in Point of Sale (HID-based scanners are supported) [https://github.com/woocommerce/woocommerce-ios/pull/15776] - [*] POS: Support refreshing product list when it's empty [https://github.com/woocommerce/woocommerce-ios/pull/15782] diff --git a/WooCommerce/Classes/ViewModels/Order Details/OrderDetailsResultsControllers.swift b/WooCommerce/Classes/ViewModels/Order Details/OrderDetailsResultsControllers.swift index 68d25ea106e..4270b4f4934 100644 --- a/WooCommerce/Classes/ViewModels/Order Details/OrderDetailsResultsControllers.swift +++ b/WooCommerce/Classes/ViewModels/Order Details/OrderDetailsResultsControllers.swift @@ -90,7 +90,7 @@ final class OrderDetailsResultsControllers { /// Products from an Order /// var products: [Product] { - return productResultsController.lightweightFetchedObjects + return productResultsController.fetchedObjects } /// ProductVariations from an Order diff --git a/WooCommerce/Classes/ViewRelated/Blaze/CampaignCreation/BlazeCampaignCreationFormViewModel.swift b/WooCommerce/Classes/ViewRelated/Blaze/CampaignCreation/BlazeCampaignCreationFormViewModel.swift index dbead3f2780..4ead8cd5fbf 100644 --- a/WooCommerce/Classes/ViewRelated/Blaze/CampaignCreation/BlazeCampaignCreationFormViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Blaze/CampaignCreation/BlazeCampaignCreationFormViewModel.swift @@ -204,7 +204,7 @@ final class BlazeCampaignCreationFormViewModel: ObservableObject { private let storage: StorageManagerType private var product: Product? { - guard let product = productsResultsController.lightweightFetchedObjects.first else { + guard let product = productsResultsController.fetchedObjects.first else { assertionFailure("Unable to fetch product with ID: \(productID)") return nil } diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewModel.swift b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewModel.swift index f1c5955c706..df7015b71f7 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewModel.swift @@ -540,7 +540,7 @@ private extension DashboardViewModel { return } - guard ordersResultsController.lightweightFetchedObjects.isEmpty else { + guard ordersResultsController.fetchedObjects.isEmpty else { hasOrders = true return } diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Items Section/WooShippingItemsDataSource.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Items Section/WooShippingItemsDataSource.swift index a76a80339b4..ff37009fa74 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Items Section/WooShippingItemsDataSource.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShipping Items Section/WooShippingItemsDataSource.swift @@ -32,7 +32,7 @@ final class DefaultWooShippingItemsDataSource: WooShippingItemsDataSource { /// private var products: [Product] { try? productResultsController.performFetch() - return productResultsController.lightweightFetchedObjects + return productResultsController.fetchedObjects } /// Stored product variations that match the items in the order. diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrderListViewModel.swift b/WooCommerce/Classes/ViewRelated/Orders/OrderListViewModel.swift index 59850dcb40c..e99b889f45e 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrderListViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrderListViewModel.swift @@ -81,7 +81,7 @@ final class OrderListViewModel { /// private var hasAnyPublishedProducts: Bool { (storageManager.viewStorage.loadProducts(siteID: siteID) ?? []) - .map { $0.toLightweightReadOnly() } + .map { $0.toReadOnly() } .contains(where: { $0.productStatus == .published }) } @@ -326,7 +326,7 @@ extension OrderListViewModel { /// Creates an `OrderListCellViewModel` for the `Order` pointed to by `objectID`. func cellViewModel(withID objectID: FetchResultSnapshotObjectID) -> OrderListCellViewModel? { - guard let order = snapshotsProvider.lightweightObject(withID: objectID) else { + guard let order = snapshotsProvider.object(withID: objectID) else { return nil } diff --git a/WooCommerce/Classes/ViewRelated/Products/ProductsViewController.swift b/WooCommerce/Classes/ViewRelated/Products/ProductsViewController.swift index 046a35554f7..502a836dc19 100644 --- a/WooCommerce/Classes/ViewRelated/Products/ProductsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Products/ProductsViewController.swift @@ -299,7 +299,7 @@ final class ProductsViewController: UIViewController, GhostableViewController { /// Selects the first product if one is available. Invoked when no product is selected when data is loaded in split view expanded mode. func selectFirstProductIfAvailable() { - guard let firstProduct = resultsController.lightweightFetchedObjects.first else { + guard let firstProduct = resultsController.fetchedObjects.first else { return } didSelectProduct(product: firstProduct) @@ -1026,7 +1026,7 @@ private extension ProductsViewController { .map { $0.productOrVariationID.id } var indexPathsToReload: [IndexPath] = [] - for (index, object) in resultsController.lightweightFetchedObjects.enumerated() { + for (index, object) in resultsController.fetchedObjects.enumerated() { if activeUploadIds.contains(object.productID) != oldIDs.contains(object.productID) { indexPathsToReload.append(IndexPath(row: index, section: 0)) } @@ -1114,7 +1114,7 @@ extension ProductsViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(ProductsTabProductTableViewCell.self, for: indexPath) - let product = resultsController.lightweightObject(at: indexPath) + let product = resultsController.object(at: indexPath) let hasPendingUploads = activeUploadIds.contains(where: { $0 == product.productID }) let viewModel = ProductsTabProductViewModel(product: product, hasPendingUploads: hasPendingUploads)