Контроллеры нескольких представлений с основными данными и Restkit

Думаю, мне здесь не хватает чего-то очевидного, так как это довольно распространенный вариант использования RestKit.

Я хочу иметь два контроллера представления, каждый из которых просто приклеивает NSFetchedResultsController к UITableView, и скажем, что первый отображает временную шкалу сообщений, а второй отображает список сообщений для определенного пользователя. Мне нужны разные списки сообщений для каждого из этих контроллеров представления, но я не могу понять, как получить эти списки с помощью RestKit.

В настоящее время я использую один и тот же NSManagedObjectContext для каждого представления, а это означает, что если у меня есть сообщение, которое существует в контроллере представления B, но не в контроллере представления A, если я вернусь к контроллеру представления A после загрузки контроллера представления B, этот пост, который должен быть уникальным для контроллера представления B теперь также отображается в контроллере представления A.

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

Это мои сопоставления:

RKEntityMapping *userMapping = [RKEntityMapping mappingForEntityForName:@"User" inManagedObjectStore:managedObjectStore];
[userMapping addAttributeMappingsFromDictionary:@{
    @"avatar_url": @"avatarURL",
    @"id":         @"userID",
    @"first_name": @"firstName",
    @"last_name":  @"lastName",
    @"username":   @"username"
}];
userMapping.identificationAttributes = @[@"userID"];

RKEntityMapping *postMapping = [RKEntityMapping mappingForEntityForName:@"Post" inManagedObjectStore:managedObjectStore];
[postMapping addAttributeMappingsFromDictionary:@{
    @"id":          @"postID",
    @"content_url": @"contentURL",
    @"created_at":  @"createdAt"
}];
postMapping.identificationAttributes = @[@"postID"];
[postMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"creator" toKeyPath:@"creator" withMapping:userMapping]];

[userMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"posts" toKeyPath:@"posts" withMapping:postMapping]];

[objectManager.router.routeSet addRoute:[RKRoute routeWithClass:[Post class] pathPattern:@"/posts\\.json" method:RKRequestMethodGET]];
[objectManager.router.routeSet addRoute:[RKRoute routeWithClass:[Post class] pathPattern:@"/posts\\.json" method:RKRequestMethodPOST]];

[objectManager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:postMapping
                                                                             pathPattern:@"/posts.json"
                                                                                 keyPath:nil
                                                                             statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];

[objectManager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:userMapping
                                                                             pathPattern:@"/_/:username.json"
                                                                                 keyPath:nil
                                                                             statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];

Это мои объекты Core Data

(StackOverflow не позволяет мне публиковать изображения…)

На мой взгляд, контроллеры - это мой fetchedResultsController геттер

- (NSFetchedResultsController *)fetchedResultsController
{
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Post" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"createdAt" ascending:NO];
    NSArray *sortDescriptors = @[sortDescriptor];

    [fetchRequest setSortDescriptors:sortDescriptors];

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error]) {
        // Replace this implementation with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _fetchedResultsController;
}

Вот как я делаю запрос от контроллера представления временной шкалы

[[RKObjectManager sharedManager] getObjectsAtPath:@"/posts.json" parameters:nil success:success failure:failure];
// The success and failure blocks don't do all that much, so I've just left them out.

Вот как я делаю запрос на контроллер представления пользователя

NSString *path = [NSString stringWithFormat:@"/_/%@.json", self.user.username];
[[RKObjectManager sharedManager] getObjectsAtPath:path parameters:nil success:success failure:failure];

person Alyssa Ross    schedule 22.05.2013    source источник
comment
Вам нужно будет показать свои сопоставления, сущности и запросы на выборку (предикаты).   -  person Wain    schedule 23.05.2013
comment
Спасибо @Wain, я добавил эту информацию сейчас (думаю).   -  person Alyssa Ross    schedule 23.05.2013


Ответы (2)


@Ross, что вы делаете неправильно, это то, что вы не фильтруете свой запрос, вы просто получаете их все, вы должны использовать NSPredicate для его фильтрации.

Вам понадобятся разные фильтры в контроллере представления A и контроллере представления B.

Вы можете создать что-то подобное, например, чтобы получать все сообщения от пользователя:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"creator.username like %@",
       self.user.username];

Чтобы получить все последние сообщения, вам даже не нужен предикат, ваш дескриптор sorte должен решить проблему.

Вот как будет выглядеть ваш метод, когда вам нужно отправить ему предикат или вы можете добавить его непосредственно в свой метод, который у вас уже есть. Теперь выбор за вами.

- (NSFetchedResultsController *)fetchedResultsController:(NSPredicate*)predicate
{
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Post" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    [fetchRequest setFetchBatchSize:20];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"createdAt" ascending:NO];
    NSArray *sortDescriptors = @[sortDescriptor];

    [fetchRequest setSortDescriptors:sortDescriptors];

    [fetchRequest setPredicate:predicate];

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error]) {
        // Replace this implementation with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _fetchedResultsController;
}

РЕДАКТИРОВАТЬ Выберите вариант 3 - у вас может быть список пользователей, на которые вы подписаны, и фильтровать ваш запрос с пользователями, а также получать все сообщения пользователей, на которых вы подписаны.

Сначала вам нужно будет получить всех пользователей, за которыми следят, а затем вы можете оценить свои сообщения с помощью подзапроса, который будет выглядеть так (я его не тестировал, возможно, что-то не так)

[NSPredicate predicateWithFormat:@"(SUBQUERY(creator, $x, $x.username IN %@).@count > 0)", followedUsernames];

Где followedUsernames - это массив со всеми именами отслеживаемых пользователей.

person ggrana    schedule 23.05.2013
comment
Спасибо @ggrana. Я вижу, как бы отфильтровать в контроллере представления пользователя, но не понимаю, как бы отфильтровать в контроллере представления временной шкалы. Там нет ничего, что идентифицирует сообщения, они появятся только в том случае, если пользователь подписался на автора. Могу ли я сделать это с помощью NSPredicate? - person Alyssa Ross; 23.05.2013
comment
Я не знаю цель вашего проекта или что вы можете в нем изменить, но у вас есть несколько вариантов. 1 - вы можете добавить поле для идентификации сообщений, которые должны отображаться в первом контроллере представления. 2 - Вы можете создавать отдельные модели. 3 - У вас может быть список пользователей, за которыми следят, и фильтровать ваш запрос с пользователями, и получать все сообщения пользователей, на которых вы подписаны. - person ggrana; 23.05.2013

Во-первых, не начинайте паттерны пути с /. Он также не нужен в начале путей в запросах.

Что касается реальной проблемы, когда вы определяете свой NSFetchedResultsController, вам также необходимо определить NSPredicate для fetchRequest. Этот предикат позволит FRC фильтровать только ту информацию, которая действительно интересует контроллеру представления (даже если ваша модель данных на самом деле содержит больше данных). Предикат будет основан на некотором переданном контроллеру значении, которое должно отображать детали для ...

Ознакомьтесь с документами предикатов здесь.

person Wain    schedule 23.05.2013