2017-01-27 4 views
2

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

В моем случае, с Realm у меня есть что-то вроде этого

class User: Object { 
    dynamic var name:String = "" 
    dynamic var email:String = "" 
    dynamic var id:String = "" 
    dynamic var picURL:String = "" 
    dynamic var pic:Data = Data() 

    static let currentUser = User() 
    { 
     didSet 
     { 
      try! realm.write { 
       realm.add(currentUser, update: true) 
      } 
    } 
    } 
} 

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

Однако приведенный выше пример показывает, что ошибка

'давайте декларации не могут быть наблюдения свойств

Как бы подойти к нему? Считаете ли вы, что моя идея с использованием объекта Realm Singleton и его обновления в любое время с некоторыми изменениями свойств - хорошая идея?

Интересно, действительно ли имеет смысл иметь одноэлементный объект класса, который сохраняется в Realm.

+0

Неясно, что вы хотите достичь: Либо можно изменить 'currentUser', то это должно быть' var', а не 'let' Или нельзя изменить 'currentUser' (так как теперь это константа' let'), но в этом случае вам не понадобится прослушиватель при настройке. –

+0

@AndreasOetjen Не могли бы вы указать, какая часть моего объяснения непонятна? – DCDC

+0

@AndreasOetjen Обратите внимание, что если я изменю его на var, он больше не будет singleton – DCDC

ответ

1

Это не возможно иметь одеяло наблюдателя для одного Realm Object в данный момент, однако есть an issue tracking it in the Realm GitHub, и я считаю, это время приоритет в данный момент.

Alcivanio верен тем, что вам нужно вручную инициировать событие обновления, чтобы гарантировать, что изменения сохраняются в Realm. При этом, поскольку Realm управляет аксессуарами в сохраняемых объектах, didSet не может быть вызван, как только объект был сохранен в Realm. Для простоты я рекомендую использовать закрытие для обновления объекта пользователя.

Обновлено Ответ: Если синглтон является Realm Object, вы не можете изменять свои свойства за пределами транзакции записи. Как я уже писал ниже, самой простой задачей было бы иметь закрытие update, которое управляло транзакцией записи Realm, и вы просто обновляете свойства своего объекта Singleton внутри него.

Как вы уже видели, вы не можете использовать didSet с свойством, определенным с помощью let, поэтому лучше всего вернуться к соглашениям Objective-C и использовать внутреннюю переменную экземпляра.

Так что все вверх, возможно, рассмотреть возможность сделать это:

fileprivate var _current: User? = nil 

class User: Object { 
    dynamic var name:String = "" 
    dynamic var email:String = "" 
    dynamic var id:String = "" 
    dynamic var picURL:String = "" 
    dynamic var pic:Data = Data() 

    static var current: User 
    { 
     if _current == nil { 
      let realm = try! Realm() 

      // Query for an existing user 
      _current = realm.objects(User.self).first 

      // Create a new user if it didn't exist in Realm 
      if _current == nil { 
       _current = User() 
       try! realm.write { realm.add(_current) } 
      } 
     } 
     return _current 
    } 

    public func update(_ block: (() -> Void)) { 
     let realm = try! Realm() 
     try! realm.write(block) 
    } 
} 

let user = User.current 
user.update { 
    user.name = "DCDC" 
} 
+0

Спасибо! К сожалению, я получаю «экземпляр участника» _current »для типа« Пользователь » – DCDC

+0

О, дорогой! Подожди. Позвольте мне попробовать его на секунду ... – TiM

+0

@DCDC Это странно. Хорошо. Я обновил ответ. Я провел некоторое исследование в синглтонах Swift и подтвердил, что этот метод работает (выведите '_current' из области действия класса). – TiM

1

Ну, если у вас только один пользователь, вы должны поместить этого наблюдателя в каждую переменную, а не в , чтобы пользователь. И там вы можете вызвать метод для обновления пользователем.

dynamic var name: String { 
    didSet{ 
     User.updateOnRealm()//create this method 
    } 
} 

Чтобы написать метод обновления, вы должны написать что-то вроде этого

class func updateOnRealm() { 
    //update code here 
} 
+0

ok, так что это единственный способ сделать это, я не могу наблюдать за всеми изменениями в объекте currentUser? – DCDC

+0

Вы хотите узнать, изменен ли «currentUser», или изменены ли какие-либо свойства пользователя? –

+0

@DCDC Похоже, что нет, вы не можете наблюдать за тем, чтобы позволить пользователю. Вы не сможете изменить пользователя, но вы сможете изменить его переменные. Поэтому для меня нет смысла наблюдать за пользователем с помощью didSet. Возможно, есть еще один способ сделать это. Поделитесь с нами, если вы найдете его :) – Alcivanio

0

Основываясь на том, что Вы писали:

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

Я хотел бы предложить это решение:

  1. Создать class User, которая не использует шаблон Singleton.

  2. Создать class UserManager который не соответствует шаблону Singleton

  3. Создание пользовательских методов сеттер для A пользователя. В этих сеттерах вы можете изменить свойства пользователей WITH или БЕЗ записи в базу данных. Вы также можете проверить использование INPUT (указать имя в нижнем регистре и т. Д.).

При таком подходе вы можете легко проверить свой User класс, расширить его, подкласс и повторное использование.

Если вам нужен комментарий к фрагментам кода ниже =).

+0

, пожалуйста, предоставьте фрагменты кода – sirvon