Как дооснастить PFObject Parse до существующего, сложного, совокупного класса моделей?
У меня есть существующий класс моделей, которым я бы хотел управлять с помощью Parse, в идеале, изменив его суперкласс с NSObject на PFObject. Но это реальный класс моделей, разработанный без учета Parse, поэтому он представляет ряд проблем.
проблемы
Проблемы:
- Этот класс в Swift.
- Этот класс имеет сохраненные свойства и вычисленные свойства. (Таким образом, Parse, конечно, должен управлять только сохраненными свойствами.)
- Некоторые свойства содержат массивы экземпляров других пользовательских классов моделей
- Некоторые из этих пользовательских классов сами содержат объекты User, которыми должен управлять Parse.
Кажется, что каждая из этих вещей требует особого подхода для правильной обработки в Parse, и документация Parse краткая по этим вопросам.
существующая иерархия классов моделей
Например, мой класс выглядит примерно так:
// I’d like to change this to be a PFUser subclass.
class User : NSObject { /* an ordinary user object */ }
// And this to be a PFObject subclass
class Tango : NSObject {
var user:User // Presumably, a Parse "Pointer" to a PFUser
var opponent:Participant
var info:NSString?
var watchers:NSArray // an array of Participants
var duration:NSTimeInterval? // (notice this is an optional value type, in accessible from Objc)
// various methods
}
// a custom class which contains a User
class Participant : NSObject
{
var status:String
var user:User // a Pointer to a PFUser?
// etc..
}
ключевые вопросы
Итак, у меня есть несколько ключевых вопросов здесь:
- Следует ли заменить все ссылки на пользователя на
Pointer
сUser
подклассPFUser
? - Нужно ли заменить Участника простым старым типом Какао, таким как NSDictionary? Или есть способ обеспечить взаимопревращение с NSDictionary только для целей внутренней сериализации Parse?
- Есть ли какое-либо положение для быстрых типов, таких как
Optional<NSTimeInterval>
? Или это другой случай, когда существует точка расширения, обеспечивающая взаимное преобразование с типом данных, который может обрабатывать Parse? - Как смоделировать массив участников? Пользователь возражает внутри Участников?
- Учитывая все эти очевидные трудности с
Tango
Буду ли я мудрее просто реализовать метод для преобразования экземпляра в / из простых старых типов plist (словари, массивы, строки, числа), и иметь PFObject обрабатывать их?
Я не заинтересован в максимальной гибкости запросов или максимальной производительности. Меня интересует самая быстрая вещь, которая может работать надежно, и которая требует минимального переписывания существующего кода, который зависит от существующей иерархии классов. Я знаю, что User / Tango
отношения могут быть описаны как многие ко многим, вот что PFRelation
для, но у меня сложилось впечатление, что для его использования потребуется серьезный редизайн.
Другими словами, я действительно надеюсь, что смогу избежать замены всего слоя моей модели на новую иерархию классов, разработанную как денормализованные таблицы для удовольствия Парса. У меня есть существующий код, который работает с текущей структурой, и я пытаюсь вписаться в Parse, не нарушая ничего там уже.
Итак, являются ли эти ключевые вопросы правильными для модернизации этого класса для Parse? Как правильно обращаться с ними?
3 ответа
Вы должны обязательно проверить руководство по подклассам. Несколько вещей, которые нужно отметить, которые особенно важны для вашего случая использования:
- Если вы подкласс встроенного класса (например,
User : PFUser
) тогда вам нужно только зарегистрировать этот подкласс. Все методы конструктора возвращаютinstancetype
так что вы можете позвонить им на пользователя и вы получите реальный пользователь обратно. Точно так же любой запрос для пользовательского класса Parse вернет результаты, десериализованные как ваш тип. - Если вы подкласс
PFObject
для ваших собственных типов, вы также должны реализовать+parseClassName
, Это сопоставляет ваш класс с именем, которое вы хотите видеть в браузере данных. Это имя должно быть одинаковым для всех языков, чтобы убедиться, что вы говорите с одними и теми же данными. PFObject
библиотека подклассов была написана только для реализации@dynamic
свойства. если ты@static
это или определить метод, тогда PFObject оставляет его в покое. Если у вас есть ивар с тем же именем, свойство не сохраняется в Parse, но вместо этого мы создадим пару аксессор / мутатор, которая учитываетPFObject
внутренняя блокировка, которую мы берем при объединении данных сервера или подготовке операции сохранения.PFObject
может обрабатывать свойства любого сериализуемого примитива JSON, указатели на другиеPFObject
их подтипы, массивы / словари иPFRelation
указатели. Я еще не играл со Swift, поэтому я не знаю, как он будет взаимодействовать с дополнительными свойствами; Я предполагаю, что они NSNumbers под одеялом иPFObject
обрабатывает NSNumbers, а также примитивы (которые автоматически упакованы / распакованы).- [Бонус] Чтобы сделать ваши подклассы автономными, вы можете добавить следующее к их определению:
// Note: +initialize is Objective-C's only non-polymorphic function; every class // must implement this directly. +(void) initialize { [self registerSubclass]; }
Мой ответ: не надо! Не имеет смысла делать классы вашей модели зависимыми от стороннего провайдера.
Создание классов подклассов классов Parse- хрупкая конструкция. Если вы хотите переключиться с Parse на что-то другое, вам придется снова изменить классы вашей модели!
Я смотрю на использование Parse в качестве бэкэнда и не планирую создавать подклассы. Вместо этого я определю протокол уровня доступа к данным с реализацией на основе Parse для получения данных от / отправки данных на сервер. Этот слой будет обрабатывать преобразование объектов из PFObjects и так далее в объекты моей модели и, наоборот, хранить данные и получать данные из Parse.
ОБНОВЛЕНИЕ: Я спросил об этом одного из разработчиков Parse iOS SDK, и он предложил использовать API Parse REST для этого подхода, поскольку создание и уничтожение объектов PFObject требует большого объема памяти. Он также отметил, что переключение бэкэнд-провайдеров довольно редко - это верно по моему опыту.
Я полагаю, что это устраняет некоторые преимущества использования Parse, но я хочу это сделать. Это по-прежнему позволяет мне избежать написания кода сервера. В вашем случае этот дизайн может быть меньше работы, так как он изолирует изменения.
Есть аналогичный вопрос в группах Google, хотя я должен сказать, что ваш вопрос более сложный. Мы знаем, что в Swift вы должны объявить свои свойства как @NSManaged public var
, Вторым шагом будет выяснить, можете ли вы установить отношения со встроенными пользователями (PFUsers). Пожалуйста, дайте нам ваше полное решение, когда вы найдете ответы на все ваши вопросы.
Смотрите следующую ссылку для шага 1: Здесь
Дополнительная информация: Я создал свой собственный объект PFObject. Я обнаружил, что когда я звоню saveInBackgroundWithBlock
блок никогда не освобождается, хотя объект на самом деле успешно сохраняется. Мой PFObject FYI
public class PatientRemote: PFObject, PFSubclassing {
public override class func load() {
self.registerSubclass()
}
public class func parseClassName() -> String! {
return "Patient"
}
@NSManaged public var firstname : NSString
@NSManaged public var lastname : NSString
@NSManaged public var birth : NSDate
@NSManaged public var idnumber : NSString
@NSManaged public var gender : NSString
@NSManaged public var fileNumber : NSString
@NSManaged public var patientPicture : NSString
@NSManaged public var medicalAid: NSString
@NSManaged public var option: NSString
@NSManaged public var mainMember: NSString
@NSManaged public var membershipNo: NSString
@NSManaged public var dependant: NSString
@NSManaged public var address1: NSString
@NSManaged public var address2: NSString
@NSManaged public var address3: NSString
@NSManaged public var address4: NSString
@NSManaged public var postalCode: NSString
@NSManaged public var workNumber: NSString
@NSManaged public var cellNumber: NSString
@NSManaged public var localId: NSString
}