Swift: как обновить трансформируемые объекты - PullRequest
1 голос
/ 18 апреля 2019

Я пытаюсь построить корзину с базовыми данными. Я создал 3 объекта для моделирования моих данных Product, Quantity и CartItem, в которых содержится продукт и количество, и я сохраняю их как преобразовываемый объект в базовых данных.

Я создал класс для моего xcdatamodeld с атрибутом CartItem

@objc(CartItemContainer)
class CartItemContainer: NSManagedObject {
    @NSManaged var cartItemAttribute: CartItem
}

Я сохраняю основные данные без проблем, но всякий раз, когда я пытаюсь обновить количество с помощью приведенного ниже кода, оно не изменяется, оно все равно будет равно 1.

    static func changeQuantity(product: Product) {

    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.persistentContainer.viewContext
    let fetchRequest = NSFetchRequest<CartItemContainer>(entityName: "CartItemContainer")

    var results: [CartItemContainer] = []
    do {
        results = try context.fetch(fetchRequest)
        if let productToChangeQuantityOn = results.first(where: {$0.cartItemAttribute.product.productID == product.productID}) {
            let oldQuantity = productToChangeQuantityOn.cartItemAttribute.quantity.value
            productToChangeQuantityOn.cartItemAttribute.quantity.value = oldQuantity + 1
            try context.save()
            context.refresh(productToChangeQuantityOn, mergeChanges: false)
        }
    }
    catch {
        print("error executing fetch request: \(error)")
    }
}

Я попытался обновить его без вызова context.refresh(productToChangeQuantityOn, mergeChanges: false) это изменило бы количество во время выполнения, но при перезапуске приложения количество все равно будет равно 1.

Что мне здесь не хватает?

Буду признателен за любую помощь.

Обновление: Вот как я настроил продукт, например. Количество и CartItem имеют одинаковые настройки.

class Product: NSObject, NSCoding, Decodable {

let productID: String
let category: String
let images: Dictionary<String, String>
let name: Dictionary<String, String>
let price: Dictionary<String, String>

func encode(with aCoder: NSCoder) {
    aCoder.encode(productID, forKey: "productID")
    aCoder.encode(category, forKey: "category")
    aCoder.encode(images, forKey: "images")
    aCoder.encode(name, forKey: "name")
    aCoder.encode(price, forKey: "price")
}

required init?(coder aDecoder: NSCoder) {
    self.productID = aDecoder.decodeObject(forKey: "productID") as! String
    self.category = aDecoder.decodeObject(forKey:"category") as! String
    self.images = aDecoder.decodeObject(forKey: "images") as! Dictionary<String, String>
    self.name = aDecoder.decodeObject(forKey: "name") as! Dictionary<String, String>
    self.price = aDecoder.decodeObject(forKey: "price") as! Dictionary<String, String>
}
}

Ответы [ 2 ]

2 голосов
/ 18 апреля 2019

Добро пожаловать в Core Data, Ахмед. Я рад, что у вас это работает. Прежде чем вы начнете, я хотел бы предложить более обычную модель данных, которая, вероятно, сработает для вас в долгосрочной перспективе. Трансформаторы не нужны. enter image description here

В общих чертах, причины приведены в первой странице Руководства по программированию базовых данных Apple , в котором указано 11 функций базовых данных , перечисленных в виде маркеров. Используя трансформируемые атрибуты вместо отношений, я бы сказал, что вы полностью понимаете преимущества только первой и пятой точек.

Что касается вашего конкретного дизайна, я предполагаю, что один и тот же продукт может быть во многих тележках. Придав CartItem a атрибут продукта типа трансформируемого , этот же продукт должен каким-то образом воспроизводиться в каждой корзине. Если вы хотите изменить атрибуты продукта, в своем дизайне вы должны найти все корзины с этим продуктом и изменить каждую из них. При традиционном дизайне вы просто меняете объект Product. Ваш дизайн требует больше кода (что всегда плохо), а устройства ваших пользователей будут использовать больше ресурсов и будут медленнее выполнять ваш код.

И последнее, но не менее важное: вы не хотите, чтобы другие инженеры ломали голову, когда они смотрели на ваш код или модель данных :) И вы хотели бы иметь возможность учиться на основе документации Apple, учебных пособий, сообщений в блогах, ответов на stackoverflow и Пример кода вы найдете в интернете. Эти ресурсы не применимы, если вы делаете вещи нетрадиционным способом.

0 голосов
/ 18 апреля 2019

Преобразуемые атрибуты являются неизменным типом, поэтому не могут быть изменены. Единственный способ изменить их - создать новый объект и снова сохранить его в основных данных.

Чтобы решить эту проблему, я удалил свойство cartItemAttribute из моего xcdatamodel, которое содержит и продукт, и количество как один преобразуемый атрибут. Я заменил его атрибутом продукта трансформируемого типа и атрибутом количества типа Int, и теперь все работает нормально.

Вот мой обновленный код

    static func changeQuantity(product: Product) {
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.persistentContainer.viewContext
    let fetchRequest = NSFetchRequest<CartItemContainer>(entityName: "CartItemContainer")

    do {
        let results = try context.fetch(fetchRequest)
        if let productToChangeQuantityOn = results.first(where: {$0.product.productID == product.productID}) {
            let oldQuantity = productToChangeQuantityOn.quantity
            productToChangeQuantityOn.quantity = oldQuantity + 1
            try context.save()
            context.refresh(productToChangeQuantityOn, mergeChanges: false)
        }
    }
    catch {
        print("error executing fetch request: \(error)")
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...