无法使用NSFetchResultController在表视图控制器中显示数据

时间:2014-04-21 00:35:36

标签: ios objective-c uitableview core-data

我正在关注核心数据教程以及如何使用NSFetchResultController,但我无法呈现数据而我无法找到问题。

以下是我的表格视图中可能出现问题的一些代码:

这是我的PatientTableViewController.h:

#import <UIKit/UIKit.h>
#import "Petient.h"

@interface PetientTableViewController : UITableViewController <NSFetchedResultsControllerDelegate>

@property (nonatomic, strong) Petient *petient;

@end

PatientTableViewController.m:

#import "PetientTableViewController.h"
#import "AppDelegate.h"
#import "AddPetientViewController.h"

@interface PetientTableViewController ()

@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;

@property (nonatomic, strong) NSFetchedResultsController *fetchResultController;

@end


@implementation PetientTableViewController


-(NSManagedObjectContext *)managedObjectContext
{
    return [(AppDelegate *)[[UIApplication sharedApplication]delegate] managedObjectContext];
}


- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSError *error = nil;

    if (![self.fetchResultController performFetch:&error]) {
        NSLog(@"Error! %@", error);
        abort();
    }
}



- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [[self.fetchResultController sections] count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchResultController sections] objectAtIndex:section];

    return [sectionInfo numberOfObjects];
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    // Configure the cell...

    Petient *petient = [self.fetchResultController objectAtIndexPath:indexPath];

    cell.textLabel.text = petient.patientLastName;
    cell.detailTextLabel.text = petient.patientFirstName;

    return cell;
}

#pragma mark - Fetched Result Controller Section

- (NSFetchedResultsController *)fetchResultController
{
    if (_fetchResultController != nil) {
        return _fetchResultController;
    }

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

    NSManagedObjectContext *context = [self managedObjectContext];

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Petient" inManagedObjectContext:context];

    [fetchRequest setEntity:entity];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"patientLastName" ascending:YES];

    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

    fetchRequest.sortDescriptors = sortDescriptors;

    _fetchResultController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];

    _fetchResultController.delegate = self;

    return _fetchResultController;
}



#pragma mark - Fetched Result Controller Delegates

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


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


-(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
    UITableView *tableView = self.tableView;

    switch (type) {
        case NSFetchedResultsChangeInsert:
        [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

        case NSFetchedResultsChangeDelete:
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

        case NSFetchedResultsChangeUpdate: {
            Petient *changePatient = [self.fetchResultController objectAtIndexPath:indexPath];
            UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
            cell.textLabel.text = changePatient.patientLastName;
        }

        break;

        case NSFetchedResultsChangeMove:
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

        default:
        break;
    }
}


-(void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
    switch (type) {
        case NSFetchedResultsChangeInsert:
        [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
        break;

        case NSFetchedResultsChangeDelete:
        [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];

        default:
        break;
    }
}

#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"addPatient"]) {
        UINavigationController *nav = [segue destinationViewController];
        AddPetientViewController *destination = (AddPetientViewController *)[nav topViewController];
        Petient *addPatient = [NSEntityDescription insertNewObjectForEntityForName:@"Petient" inManagedObjectContext:self.managedObjectContext];

        destination.addPatient = addPatient;
    }

}


@end

这是我的模型类Petient.h:

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@class Prescription;

@interface Petient : NSManagedObject

@property (nonatomic, retain) NSString * patientLastName;
@property (nonatomic, retain) NSString * patientFirstName;
@property (nonatomic, retain) NSSet *prescriptions;
@end

@interface Petient (CoreDataGeneratedAccessors)

- (void)addPrescriptionsObject:(Prescription *)value;
- (void)removePrescriptionsObject:(Prescription *)value;
- (void)addPrescriptions:(NSSet *)values;
- (void)removePrescriptions:(NSSet *)values;

@end

这是我的AddPatientViewController.h:

#import <UIKit/UIKit.h>
#import "CoreViewController.h"
#import "Petient.h"

@interface AddPetientViewController : CoreViewController

@property (weak, nonatomic) IBOutlet UITextField *patientFirstName;

@property (weak, nonatomic) IBOutlet UITextField *patientLastName;

@property (nonatomic, strong) Petient *addPatient;


// Actions

- (IBAction)cancel:(UIBarButtonItem *)sender;

- (IBAction)save:(UIBarButtonItem *)sender;

@end

这是我的AddPatientViewController.m:

#import "AddPetientViewController.h"

@interface AddPetientViewController ()

@end

@implementation AddPetientViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


- (IBAction)cancel:(UIBarButtonItem *)sender
{
    [super cancelAndDisMiss];
}

- (IBAction)save:(UIBarButtonItem *)sender
{
    self.addPatient.patientFirstName = _addPatient.patientFirstName;
    self.addPatient.patientLastName = _addPatient.patientLastName;
    [super saveAndDismiss];
}
@end

2 个答案:

答案 0 :(得分:1)

您需要实际实现NSFetchedResultsControllerDelegate的委托方法,以便告诉表何时加载内容。例如,当调用-controllerWillChangeContent时,可以在表上调用 -reloadData

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

答案 1 :(得分:1)

- (IBAction)save:(UIBarButtonItem *)sender中,你得到了:

self.addPatient.patientFirstName = _addPatient.patientFirstName;
self.addPatient.patientLastName = _addPatient.patientLastName;

这不应该来自UITextField s?

self.addPatient.patientFirstName = self.patientFirstName.text;
self.addPatient.patientLastName = self.patientLastName.text;