primaryKeyAttribute не работает Restkit / Core Data - PullRequest
4 голосов
/ 18 октября 2011

Я только что установил restkit фреймворка 0.9.3 и последовал примеру доски обсуждений.Что ж, все просто отлично работало, однако когда я пытался использовать Core Data, мой класс NSManagedObject пользователя дублируется даже после объявления его primaryKeyAttribute (userID).Например, когда я отправляю запрос на вход в систему на своем веб-сервере, я возвращаю {"user":{"id":1, "username":"teste", ...}} .., но создается впечатление, что он создает новую строку при каждом вызове objectLoader: didLoadObjects.

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

enter image description here

Пример кода:

~ AppDelegate.m didFinishLaunching

RKManagedObjectMapping* userMapping = [RKManagedObjectMapping mappingForClass:[User class]];    
userMapping.primaryKeyAttribute = @"userID";
userMapping.setDefaultValueForMissingAttributes = YES; // clear out any missing attributes (token on logout)
[userMapping mapKeyPathsToAttributes:
     @"id", @"userID",
     @"email", @"email",
     @"username", @"username",
     @"password", @"password",
     nil];

[objectManager.mappingProvider registerMapping:userMapping withRootKeyPath:@"user"];

~ User.m loginWithDelegate

- (void)loginWithDelegate:(NSObject<UserAuthenticationDelegate>*)delegate {
    _delegate = delegate;   
    [[RKObjectManager sharedManager] postObject:self delegate:self block:^(RKObjectLoader* loader) {
        loader.resourcePath = @"/login";
        loader.serializationMapping = [RKObjectMapping serializationMappingWithBlock:^(RKObjectMapping* mapping) {
            [mapping mapAttributes:@"username", @"password", nil];            
        }];
    }];
}

~ User.m didLoadObjects (RKObjectLoaderDelegate)

- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray *)objects {

    if ([objectLoader wasSentToResourcePath:@"/login"]) {
        [self loginWasSuccessful];
    }

    NSLog(@"number of user rows: %i", [User findAll].count);
}

Что я делаюнеправильно?

Ответы [ 3 ]

2 голосов
/ 30 апреля 2012

Правильно ли вы внедряете RKManagedObjectCache?Для отладки я просто вернул ноль и забыл об этом.Некоторое время спустя я обнаружил, что у меня также есть дубликаты.

Кэш работает путем выборки локальных объектов и сравнения с возвращенными объектами сервера.Любые локальные объекты, которых нет в ответе сервера, будут удалены.В более ранних версиях он использовал запрос выборки, но в более новых версиях вы должны вручную выполнить запрос и вернуть фактические объекты.

Если вы вернете nil, он думает, что этого объекта нет в вашем кэше, и добавит дубликат.Попробуйте реализовать этот метод:

+ (NSManagedObject *)findInstanceOfEntity:(NSEntityDescription *)entity
              withPrimaryKeyAttribute:(NSString *)primaryKeyAttribute
                                value:(id)primaryKeyValue
               inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext

Например:

+ (NSManagedObject *)findInstanceOfEntity:(NSEntityDescription *)entity
              withPrimaryKeyAttribute:(NSString *)primaryKeyAttribute
                                value:(id)primaryKeyValue
               inManagedObjectContext:(NSManagedObjectContext *)managedObjectContext {

    NSFetchRequest* request = [[NSFetchRequest alloc] init];
    [request setEntity: entity];
    [request setFetchLimit: 1];
    [request setPredicate:[NSPredicate predicateWithFormat:@"%K = %@", primaryKeyAttribute, primaryKeyValue]];

    NSArray *results = [NSManagedObject executeFetchRequest:request inContext: managedObjectContext];
    if ([results count] == 0)
    {
     return nil;
    }
    return [results objectAtIndex:0];
}
2 голосов
/ 21 октября 2011

Я обнаружил проблему, связанную с targetObject (RKObjectLoader)

/**
 * The target object to map results back onto. If nil, a new object instance
 * for the appropriate mapping will be created. If not nil, the results will
 * be used to update the targetObject's attributes and relationships.
 */

Так что, когда я установил его на nil, postObject вызывает findOrCreateInstanceOfEntity: withPrimaryKeyAttribute: andValue

- (void)loginWithDelegate:(NSObject<UserAuthenticationDelegate>*)delegate {
    _delegate = delegate;   
    [[RKObjectManager sharedManager] postObject:self delegate:self block:^(RKObjectLoader* loader) {
        loader.resourcePath = @"/login";
        loader.targetObject = nil;
        loader.serializationMapping = [RKObjectMapping serializationMappingWithBlock:^(RKObjectMapping* mapping) {
            [mapping mapAttributes:@"username", @"password", nil];            
        }];
    }];
}
0 голосов
/ 29 июля 2014

Начиная с последней версии RESTKit (0.23.2), вы можете определить первичный ключ следующим образом:

[_mapping addAttributeMappingsFromDictionary:@{ @"id" : @"objectId", @"name" : @"name" }];
[_mapping setIdentificationAttributes:@[ @"objectId" ]];

Принимая во внимание, что objectId - ваш первичный ключ в основном объекте данных.

...