2015-06-22 2 views
2

Постараюсь быть максимально информативным с этим вопросом ...Mapping отношения с JSON массива с Restkit

Сценарий

Допустим, у меня есть NSManagedObject 'User'

@class Premise; 

@interface User : NSManagedObject 

@property (nonatomic, retain) NSNumber * identifier; 
@property (nonatomic, retain) NSString * name; 
@property (nonatomic, retain) NSSet *premises; 
@end 

@interface User (CoreDataGeneratedAccessors) 

- (void)addPremisesObject:(Premise *)value; 
- (void)removePremisesObject:(Premise *)value; 
- (void)addPremises:(NSSet *)values; 
- (void)removePremises:(NSSet *)values; 

@end 

И у меня также есть NSManagedObject '' Помещение

@class User; 

@interface Premise : NSManagedObject 

@property (nonatomic, retain) NSNumber * identifier; 
@property (nonatomic, retain) NSString * name; 
@property (nonatomic, retain) User *user; 

@end 

Основываясь на этом, я создаю маршрут отношений для сопоставления массива JSON «Помещения» с атрибутом «помещения» объекта «Пользователь».

Вот маршрут:

let getPremisesRoute = RKRoute(relationshipName: "premises", 
           objectClass: User.self, 
           pathPattern: "user/:identifier/premises", 
           method: .GET) 

Вот ответ JSON (/ пользователь/1/помещения):

[ 
    { 
     "id": 35, 
     "name": "Icaraí" 
    }, 
    { 
     "id": 32, 
     "name": "Remanso" 
    } 
] 

Вот дескриптор ответа:

let getPremisesResponseDescriptor = RKResponseDescriptor(mapping: premiseMapping, method: .GET, pathPattern: "user/:identifier/premises", keyPath: nil, statusCodes: RKStatusCodeIndexSetForClass(.Successful)) 

И вот соответствующие сопоставления «Пользователь» и «Помещения»

let userMapping = RKEntityMapping(forEntityForName: "User", inManagedObjectStore: moc) 
userMapping.addAttributeMappingsFromDictionary(["id":"identifier", "name":"name"])  
userMapping.identificationAttributes = ["identifier"] 
userMapping.addPropertyMapping(RKRelationshipMapping(fromKeyPath: nil, toKeyPath: "premises", withMapping: premiseMapping)) 


let premiseMapping = RKEntityMapping(forEntityForName: "Premise", inManagedObjectStore: moc) 
premiseMapping.addAttributeMappingsFromDictionary(["id":"identifier", "name":"name"]) 
premiseMapping.identificationAttributes = ["identifier"] 

Теперь к моей проблеме

Видимо, Restkit становится немного запутался в процессе отображения. Вот база данных после запроса: Таблица

Пользователь: enter image description here

Предпосылка Таблица:

enter image description here

Обратите внимание на связь не создается между объектами.

Теперь, если я изменю отображение дескриптора отклика в от помещения в пользователя отображения, изменения базы данных в этом:

Пользователи Таблица:

enter image description here

Предпосылка Таблица:

enter image description here

Я действительно смущен тем, что происходит, и я пробовал много решений без успеха.

Является ли ответ JSON неправильным или я что-то не так? Ответ JSON, по-видимому, имеет общую схему с нулевым ключом.

ответ

1

Вы неправильно приближаетесь к отображению, или, по крайней мере, ваши сопоставления неверны для того, что вы делаете.Учтите, что ответ - это пользователь, но только помещения для пользователя, вместо того, чтобы рассматривать его как простой список помещений, как вы сейчас. Затем вы сопоставляете пользователя и вставляете помещение. Что-то вроде:

RKResponseDescriptor(mapping: userMapping, method: .GET, pathPattern: "user/:identifier/premises", keyPath: nil, statusCodes: RKStatusCodeIndexSetForClass(.Successful)) 

А вот соответствующие отображения «User» и «предпосылке»

let userMapping = RKEntityMapping(forEntityForName: "User", inManagedObjectStore: moc) 
userMapping.addAttributeMappingsFromDictionary(["@metadata.routing.parameters.idEntities":"identifier"])  
userMapping.identificationAttributes = ["identifier"] 
userMapping.addPropertyMapping(RKRelationshipMapping(fromKeyPath: nil, toKeyPath: "premises", withMapping: premiseMapping)) 


let premiseMapping = RKEntityMapping(forEntityForName: "Premise", inManagedObjectStore: moc) 
premiseMapping.addAttributeMappingsFromDictionary(["id":"identifier", "name":"name"]) 
premiseMapping.identificationAttributes = ["identifier"] 

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

+0

Я получаю часть метаданных, но это решение имеет другую проблему. Если я изменяю «пользовательское» сопоставление, как вы предлагаете, момент, когда я запрашиваю свой пользовательский объект с сервера (например, для входа в систему), Restkit не будет отображать атрибут «id», переданный как JSON, в «идентификатор», он вместо этого будет искать метаданные и не найдет их, таким образом, равный «id» на «nil». Должен ли я создавать множественные сопоставления для объекта «user»? –

+1

Используя этот подход, у вас есть несколько сопоставлений, да. На это нет никаких ограничений. – Wain

1

Хорошо, я нашел возможное решение на основе решения @ Wain с использованием внешних ключей.

Я добавил новое свойство «USERID» в «Premise» объекта и отображается его идентификатор на URL с использованием метаданных

let premiseMapping = RKEntityMapping(forEntityForName: "Premise", inManagedObjectStore: moc) 

premiseMapping.addAttributeMappingsFromDictionary(["id":"identifier", "name":"name", "@metadata.routing.parameters.identifier":"userID"]) 

Затем я добавил связь отношения к «premiseMapping»

premiseMapping.addConnectionForRelationship("user", connectedBy: ["userID":"identifier"]) 

Если у кого-то есть более элегантное решение, пожалуйста, поделитесь с нами.

+1

Это, как правило, другой вариант (есть два конца, с которыми вы можете настроить отношения, и это 2 метода для этого ...) – Wain