如何从Restkit中的UITableView清除NSFetchedResultsController结果

时间:2014-02-27 09:59:32

标签: ios objective-c uitableview core-data restkit

我有一个主人UITableView程序,点击的每个单元格都会导致与所点击的程序相关的另一个UITableView剧集

问题:每次我点击一个程序单元格时,它会将我点击的最后一个程序的剧集追加到剧集表视图控制器中。

示例:假设节目A有剧集i,ii,然后点击剧集A在桌子上显示i,ii 假设节目B有剧集iii,然后点击剧集B显示i,ii,iii而不仅仅是iii

我尝试了什么:我确保每次点击一个programcell时我总是从头开始实例化EpisodesDataSource,每次点击程序单元格时我都会销毁NSFetchedResultsController实例。我也确保我不会多次添加相同的响应描述符..而且我也使用了

[NSFetchedResultsController deleteCacheWithName:@"Master"];

每次我拨打fetchedResultsController ..但仍然没有运气..请参阅下面的实施细节。

ProgramsViewController

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    Controller *controller = [Controller getSingleton];

    MediaListViewController *episodesVC = 
    [controller.storyboard instantiateViewControllerWithIdentifier:@"NewsReportsViewController"];
    ProgramCell *programCell = (ProgramCell *)[tableView cellForRowAtIndexPath:indexPath];

    episodesVC.dataSource = [[EpisodesDataSource alloc] initWithProgramId:programCell.programId];

    [self.navigationController episodesVC animated:YES];
}

EpisodesDataSource

@implementation EpisodesDataSource

- (id)initWithProgramId:(NSNumber *)programId {
    self = [self init];
    self.programId = programId;
    self.parameters = @{@"pid": programId};
    self.predicate = @"episode";
    return self;
}

- (id)init {
    self = [super init];
    self.entityName = @"Episodes";
    self.resourcePath = kEpisodesPath;
    self.sortKey = @"episode_title";
    self.keyPath = @"EpisodesList.Episode";
    return self;
}

- (void)addResponseDescriptor {

    Model *model = [Model getSingleton];
    NSArray *existingResponseDescriptors = [model.objectManager.responseDescriptors mapObjectsUsingBlock:^(RKResponseDescriptor *descriptor, NSUInteger idx){
        return [descriptor keyPath];
    }];

    if ([existingResponseDescriptors containsObject:self.keyPath]) {
        NSLog(@"response descriptor %@ already exsits! return", self.keyPath);
        return;
    }

    NSLog(@"adding response descriptor %@", self.keyPath);
    RKEntityMapping *episodesEntityMapping = [RKEntityMapping mappingForEntityForName:self.entityName inManagedObjectStore:model.managedObjectStore];
    // left is http, right is dbase
    [episodesEntityMapping addAttributeMappingsFromDictionary:@{@"programId.text":       @"episode_id",
                                                                @"EpisodeTitle.text":    @"episode_title",
                                                                @"EpisodeImageUrl.text": @"episode_image_url",
                                                                @"EpisodeNewsUrl.text":  @"episode_news_url",
                                                                @"EpisodeVideoUrl.text": @"episode_video_url",
                                                                @"EpisodeVideoId.text":  @"episode_video_id",
                                                                @"EpisodeCaption.text":  @"episode_caption",
                                                                @"EpisodeDetails.text":  @"episode_details",
                                                                }];

    episodesEntityMapping.identificationAttributes = @[ @"episode_id" ];


    RKResponseDescriptor *episodesResponseDescriptor =
    [RKResponseDescriptor responseDescriptorWithMapping:episodesEntityMapping
                                                 method:RKRequestMethodAny
                                            pathPattern:self.resourcePath
                                                keyPath:self.keyPath
                                            statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];


    [model.objectManager addResponseDescriptor:episodesResponseDescriptor];

}

并在 MediaListViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // setup delegates
    NSAssert(dataSource, @"Datasource of MediaListViewController cannot be nil");
    dataSource.tableViewController = self;
    self.tableView.dataSource = dataSource;

    // setup refresh controller
    UIRefreshControl *refreshControl = [UIRefreshControl new];
    [refreshControl addTarget:self action:@selector(refreshData) forControlEvents:UIControlEventValueChanged];
    self.refreshControl = refreshControl;

    // load data
    [dataSource addResponseDescriptor];
    [dataSource downloadData];
    Controller *controller = [Controller getSingleton];
    UIView *background = [[UIView alloc] initWithFrame:controller.window.frame];
    [background setBackgroundColor:[UIColor redColor]];
    [background setTag:999];
    [[self.tableView superview] addSubview:background];
    [[self.tableView superview] sendSubviewToBack:background];
}

EpisodesDataSource 继承自 DataSource:,其中包含:

- (NSFetchedResultsController *)fetchedResultsController
{
    // reset
    [NSFetchedResultsController deleteCacheWithName:@"Master"];

    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }

    NSManagedObjectContext *context =((Model *)[Model getSingleton]).managedObjectStore.mainQueueManagedObjectContext;

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:self.entityName
                                              inManagedObjectContext:context];
    [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:self.sortKey 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:context
                                            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;
}

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
    [tableViewController.tableView beginUpdates];
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    [tableViewController.tableView endUpdates];
}

1 个答案:

答案 0 :(得分:1)

根据@Duncan Groenewald的评论,您应该使用谓词来过滤掉数据存储的内容,这样您才能显示子集。目前,您每次处理新下载时都会显示所有内容,您将获得其他表格视图内容。


对于后续问题,请检查谓词。当您期望匹配时(即将字符串“100”与数字100进行比较),托管对象和谓词中使用的类/数据类型不匹配可能会导致失败。

通常,托管对象中的所有相同类型的信息都应该与数据类型匹配,并且当从主接口移动到详细接口时,您应该传递托管对象(或来自托管对象的值)以确保您保持一致性提取/过滤时。