Рекомендации Realm: как обрабатывать асинхронное обновление HTTP-объекта?

#ios #swift #realm

#iOS #swift #realm

Вопрос:

У меня есть модель, которая является объектом swift.

Я извлекаю данные из Интернета, а затем мне нужно обновить свой объект, но есть разные случаи для обработки:

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

И вот как я с этим справляюсь:

  1. Если self.invalidated == false amp; self.realm == nil -> обновить свойства для self

  2. Если self.invalidated == false amp; self.realm != nil -> Извлеките объект из Realm в фоновом потоке, установите свойства, обновите Realm в основном потоке до завершения

  3. Если self.invalidated == true -> Stop (объект удален, поэтому он больше не нужен)

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

Не могли бы вы дать мне некоторое представление о том, какой самый чистый способ справиться с таким случаем?

Вот мой код на данный момент:

 func fetchDataOnline(completion:(success : Bool)->()){

    let params = ["tmdb_id":self.tmdbId,"lang":kLang]

    let tmdbId = self.tmdbId

    let invoker = AWSLambdaInvoker.defaultLambdaInvoker()
    invoker.invokeFunction("getMovie", JSONObject: params).continueWithBlock { (task) -> AnyObject? in

        guard self.invalidated == false else{
            DDLogWarn("Movie has been invalidated while fecthing data")
            completion(success: false)
            return nil
        }

        if let dic = task.result as? NSDictionary{

            var objectToUpdate = self

            if self.realm != nil{ //Use new realm instance
                guard let newRealmInstance = try! Realm().objectForPrimaryKey(MovieNew.self, key: tmdbId) else{
                    DDLogError("self.realm not nil but can't find movie in realm")
                    completion(success: false)
                    return nil
                }

                objectToUpdate = newRealmInstance
            }

            try! Realm().write{
                objectToUpdate.setProperties(dic: dic)
                objectToUpdate.lastUpdate = NSDate()
            }
        }
        else{ //No dictionary found from result
            if let error = task.error{
                DDLogError(error.description)
            }
            DDLogError("Error getting movie")
        }

        Async.main{
            try! Realm().refresh()
            completion(success : task.error == nil)
        }

        return nil
    }
}
  

Ответ №1:

Учитывая ваши конкретные сценарии использования, я думаю, что это выглядит как лучший способ сделать это. Хотя вы могли бы отслеживать состояние внутри самих объектов Realm, гораздо лучше просто отслеживать их статус по отношению к их родительским объектам Realm и реагировать на это соответствующим образом.

Основная рекомендация для Realm в основном заключается в том, чтобы попытаться как можно больше минимизировать количество транзакций записи., поэтому единственное, что я мог бы здесь задать, — это если абсолютно необходимо добавить объект в Realm перед выполнением запроса, только для того, чтобы потенциально удалить его снова перед загрузкой.завершено. Если это необходимо, потому что вы используете эти объекты в качестве заполнителей в своем пользовательском интерфейсе, то это совершенно нормально.

В любом случае, все это действительно вопрос мнения. Это предложенное вами решение является компетентным и удовлетворяет всем вашим требованиям, поэтому я не уверен, стоит ли пытаться найти что-то лучшее. 🙂