2015-07-03 3 views
3

Ради вопроса, вот простой пример (с несколькими ярлыками):Realm Swift: Обновление объекта внутри закрытия

class Foo: Object { 
    dynamic var id: Int = 0 
    [...] 
} 

class Bar: Object { 
    dynamic var id: Int = 0 
    dynamic var foo: Foo? 

    convenience required init(data: AnyObject) { 
    self.init() 
    self.id = data.id as! Int 

    if let foo_id = data.foo_id as? Int { 
     // Function querying the remote database and returning an object 
     Foo.get(foo_id) { (foo) -> Void in 
     self.foo = foo // Foo object assigned, as expected 
     } 
    } 
    } 
} 

Если я делаю self.foo = foo в закрытии get() функция, я получил исключение:

исключение «RLMException», причина: "Попытка изменить объект за пределами транзакции записи - вызов beginWriteTransaction на RLMRealm экземпляр первого.

Так что, если я хочу добавить realm.write вокруг него, как на вопрос предыдущего исключения:

... 
Foo.get(foo_id) { (foo) -> Void in 
    let realm = Realm(path: Realm.defaultPath) 
    realm.write { 
    self.foo = foo 
    } 
} 
... 

На этот раз я получить новый один:

исключение «RLMException ', причина: «Невозможно добавить объекты из другого королевства»

Я застрял, и я не могу понять, что такое Realm is wantin g от меня здесь, док не помогает.

Я не привык к царству, поэтому я полагаю, что у меня что-то не так, как это работает, но я не знаю, что.

Спасибо за вашу помощь

+0

Выполняете ли вы это на объекте, который уже был сохранен в * ЛЮБОМ * другом Царстве? Что-то еще, чем 'Realm.defaultPath'?Первое исключение очевидно - либо 'beginWriteTransaction()' -> write -> 'commitWriteTransaction()', либо блок, который вы упомянули. Другое исключение возникает, когда вы пытаетесь обновить объект в ** неправильном ** царстве, чем тот, который вы уже сохранили. – Michal

+0

У меня только одно царство, я использую по умолчанию. Я думал, что это может быть связано с использованием 'self' в закрытии после того, как объект был инициализирован? – Sylver

+0

Я также попробовал 'self.realm.write() {...}', но 'self.realm' является необязательным и равен нулю при попытке написать мой объект, поэтому я не вижу смысла использовать этот код – Sylver

ответ

4

ОК, так что проблема заключается в следующем - вы пытаетесь открыть write() сеанс, когда объект не сохраняется в Realm в самом инициализаторе и я думаю, что эта структура не очень счастлив об этом.

Моя рекомендация для подхода заключается в следующем:

  1. Установите значения, которые вы знаете, прежде чем получить данные из базы данных в объекте, а остальное, что вы не установите либо значений некоторых по умолчанию или установить их как необязательные значения.
  2. Сохраните объект в области, а затем вызовите загрузку в закрытии (асинхронно, конечно), - которая возьмет объект в закрытии и потому что к тому времени объект будет сохранен в области, вы сможете напрямую доступ savedObject.realm, и вы сможете писать правильно без исключений.
+1

Я подтвердил ваш ответ, потому что это правильно, но я не полностью согласен с вашими рекомендациями. Я опубликовал еще один ответ, который должен предоставить ОП с другой точки зрения. Спасибо за ответ! – jpsim

1

tl; dr; вы не можете назначить объект сохраненного объекта Realm объекту объекта, который не был сохранен.

Было бы полезно знать, что делает Foo.get(_:). Я предполагаю, что он создает постоянный объект Realm (возможно, даже в другом потоке), тогда как объект Bar никогда не сохраняется (вызов super.init() будет просто создавать отдельный объект, не привязанный к любому царству).

Если мои предположения о Foo.get(_:) верны, просто создайте автономный Foo в этой функции. Тогда вы сможете установить его как Bar 's собственность за пределами любой транзакции записи.