iOS Mantle + Пальто
Я смотрю на библиотеку Overcoat, которая из того, что я собираю, является библиотекой, расширяющей библиотеку Mantle.
Мантия: https://github.com/Mantle/Mantle/ Пальто: https://github.com/gonzalezreal/Overcoat
На страницах Mantle и Overcoat github постоянно упоминается о создании модели Mantle, но я хочу знать, как мне создать модель Mantle? Нужно ли вводить его вручную или использовать файл Xcode xcdatamodel для его визуального построения, а затем создать подкласс + изменить этот файл впоследствии?
В Базовых данных создайте сущность в файле xcdatamodel, используя Интерфейсный Разработчик, затем используйте Редактор XCode> Создать NSManagedObject подкласс.
Делаем ли мы то же самое для Mantle, а затем меняем NSManagedObject на MTLModel?
Что происходит, когда мы решили обновить сущность Core Data в файле xcdatamodel? Если мы снова создадим файл модели, не придется ли нам снова добавить все эти изменения в класс NSManagedObject?
Супер запутался в процессе.
1 ответ
Хорошо, я думаю, что начинаю понимать это немного больше. После нескольких часов проб и ошибок я смог получить базовое демонстрационное приложение Overcoat, работающее с извлечением Core Data из моего REST API.
Я получил это работать так:
1) Мы создаем сущности внутри файла xcdatamodel, НО НЕ генерируем класс NSManagedObject, используя меню "Редактор"> "Создать классы NSManagedObject".
2) Создайте подкласс модели Mantle для обычной папки проекта правой кнопки мыши (в XCode) > Новый файл> Выберите MTLModel в качестве подкласса и затем вручную введите свойства. Примечательно, что заголовок подкласса должен быть примерно таким:
@interface Book : MTLModel <MTLJSONSerializing, MTLManagedObjectSerializing>
@property (nonatomic, copy) NSString *title;
...
@end
3) Если вы случайно сгенерировали сущность Core Data, такую как я, файл xcdatamodel фактически добавляет имя класса в раздел "Default" в разделе "Configuration" внутри xcdatamodel.
Вам нужно удалить любое значение в столбце "Класс", в противном случае вы получите неудачное сообщение:
"XYZ" is not a subclass of NSManagedObject.
4) Убедитесь, что в вашем классе модели Mantle реализованы методы сериализации для MTLJSONSerialization и MTLManagedObjectSerializing.
#pragma mark - MTLJSONSerialization -
+(NSDictionary *)JSONKeyPathsByPropertyKey
{
return @{
@"title": @"title",
...
};
}
#pragma mark - MTLManagedObjectSerializing -
+(NSString *)managedObjectEntityName
{
// ------------------------------------------------
// If you have a Core Data entity called "Book"
// then you return @"Book";
//
// Don't return the Mantle model class name here.
// ------------------------------------------------
return @"TheCoreDataEntityName";
}
+(NSDictionary *)managedObjectKeysByPropertyKey
{
// ------------------------------------------------
// not really sure what this does, I just put
// it in as the example does it too
// ------------------------------------------------
return @{};
}
Эти методы, по сути, являются связующим звеном, отображающим ответ JSON с сервера на основные объекты данных.
5) Еще одна важная вещь, которую я получил, - это способ, которым сервер возвращает ответы.
Ваш сервер может использовать код статуса HTTP, а не словарь JSON верхнего уровня
например
// no top level JSON dictionary, purely just an array of results
{
{
title: "ABC",
...
},
{
title: "ABC",
...
},
{
title: "ABC",
...
},
}
Принимая во внимание, что другие типы REST-сервера могут возвращать словарь JSON верхнего уровня с путем ключа результатов на подуровне, например:
{
count: 20,
next: "http://www.server.com/api/resource?page=2",
previous: null,
results:(
{
title: "ABC",
...
},
{
title: "ABC",
...
},
{
title: "ABC",
...
})
}
В последнем случае это называется ответом "Envelop" из моего смутного понимания. Для этого типа ответов сервера существует дополнительный шаг, который включает в себя указание Overcoat, где в ответе JSON находится путь ключа массива результатов.
Для этого нам необходимо:
5a) Создайте класс ServerResponse, который является подклассом OVCresponse:
// .h file
#import "OVCResponse.h"
@interface ServerResponse : OVCResponse
@end
// .m file
@implementation ServerResponse
+(NSString *)resultKeyPathForJSONDictionary:(NSDictionary *)JSONDictionary
{
// --------------------------------------------------------------------
// we're telling Overcoat, the array of entities is found under the
// "results" key-value pair in the server response JSON dictionary
// --------------------------------------------------------------------
return @"results";
}
@end
5b) В вашем классе APIClient (который должен быть подклассом OVCHTTPSessionManager
), переопределите метод:
+(Class)responseClass
{
// --------------------------------------------------
// ServerResponse class will let Overcoat know
// where to find the results array
// --------------------------------------------------
return [ServerResponse class];
}
Надеюсь, это поможет всем, кто испытывает ту же проблему, пытаясь заставить работать пальто.