Локальное хранилище данных Parse.com: попытка сохранить объект с новым несохраненным дочерним элементом

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

Рассмотрим классы Product и Order:

class Product : PFObject, PFSubclassing {
    @NSManaged var productName: String!
}

class Order : PFObject, PFSubclassing {
    @NSManaged var orderId: String!
    @NSManaged var product: Product!
}

С отключенным Интернетом, когда я запускаю следующий код, он падает в последней строке с Tried to save an object with a new, unsaved child.

let p = Product()
p.productName = "Test Product"
p.saveEventually()

let o = Order()
o.orderId = "TestOrder01"
o.product = p
o.saveEventually()

let query = Order.query()
query.whereKey("product", equalTo: p)

let results = query.findObjects() // crashes with Tried to save an object with a new, unsaved child.

это ограничение платформы или ошибка в моем коде?

ПРИМЕЧАНИЕ Я набрал код по памяти, поэтому не обращайте внимания на незначительные проблемы.


person User123    schedule 29.12.2014    source источник


Ответы (3)


Это вызвано тем, что вы используете saveEventually, вызывая состояние гонки, например:

  1. Вы создаете Продукт.
  2. Вы говорите Parse сохранить его, когда у него будет время, но это происходит не сразу.
  3. Вы создаете Орден.
  4. Когда вы указываете Parse сохранить порядок в конце концов, он проверяет, чтобы родитель уже был сохранен, а это не так, отсюда и ошибка.

Перед созданием дочернего элемента необходимо убедиться, что родитель сохранен.

Вместо этого выполните saveInBackGroundWithBlock для Продукта, а затем создайте и сохраните Заказ в блоке завершения.

person Ryan Kreager    schedule 29.12.2014
comment
Вы правы, но я хочу сказать, что не следует saveEventually() сохранять данные в локальном хранилище данных (поскольку у пользователя нет Интернета)? Это очень распространенный сценарий, когда пользователь создает объекты и код, запрашивающий их для обновления пользовательского интерфейса (в автономном режиме). Итак, это действительно ограничение платформы. Нельзя выполнять запросы, если данные уже не сохранены онлайн, верно? - person User123; 30.12.2014

Вам может понадобиться метод pinObjectInBackground. Именно так вы сохраняете локально.

Метод saveEventually используется, когда вы хотите синхронизировать локальные данные с облаком. saveEventually закрепляет, но сохраняет в облаке при первой же возможности.

Когда вы просто pinObjectInBackground, он сохраняет его локально, но не будет пытаться сохранить что-либо в автономном режиме.

person Kerkness    schedule 05.03.2015

См. код ниже. Осторожно, я изменил его без XCODE, так что в нем могут быть опечатки :) Приведенный ниже код будет выглядеть так, чтобы удовлетворить ваш запрос из локального хранилища данных. «saveEventually» будет передаваться (синхронизироваться) с облаком Parse, но если вы хотите, чтобы данные были локально доступны, они должны быть закреплены, с именем или без него.

let p = Product()
p.productName = "Test Product"
p.pinWithName("test")
p.saveEventually()

let o = Order()
o.orderId = "TestOrder01"
o.product = p

o.pinWithName("test")
o.saveEventually()

let query = Order.query()
query.fromPinWithName("test")
query.whereKey("product", equalTo: p)

let results = query.findObjects() 
person weePee    schedule 11.05.2015