2

我有一些“细节”保存到我的核心数据中,我正试图将它从NSFetchedResultsController我的tableView. 无论出于何种原因,tableView一旦块完成运行,就不会填充。

我一直在寻找和询问我可以尝试找出整个核心数据崩溃的地方。希望这里有人能帮助我!

主视图控制器.m

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.navigationItem.title = @"Home";
    self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:0 green:0.7 blue:2.3 alpha:1];

    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCompose target:self action:@selector(addShindy:)];

    self.tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"light_alu.png"]];
    self.tableView.opaque = NO;
    self.tableView.backgroundView = nil;

    UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
    [refreshControl addTarget:self action:@selector(refresh:)
             forControlEvents:UIControlEventValueChanged];
    self.refreshControl = refreshControl;

    [self setShindyDatabase:self.shindyDatabase];

}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    if (!self.shindyDatabase) {
        NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
        self.shindyDatabase = [[UIManagedDocument alloc] initWithFileURL:url];
    }
}

- (void)refresh:(UIRefreshControl *)sender
{
    [self useDocument];
    [sender endRefreshing];
}

- (void)addShindy:(UIBarButtonItem *)sender
{
    AddShindyViewController *addShindyViewController = [[AddShindyViewController alloc] initWithNibName:@"AddShindyViewController" bundle:nil];
    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:addShindyViewController];
    [self presentViewController:navController animated:YES completion:nil];
}

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

#pragma Core Date Stack

- (void)fetchShindyDataIntoDocument:(UIManagedDocument *)document
{
    dispatch_queue_t fetchIntoDocument = dispatch_queue_create("Fetch Into Document", nil);
    dispatch_async(fetchIntoDocument, ^{
        NSArray *shindys = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        for (NSDictionary *shindyInfo in shindys) {
            [Shindy shindyWithShindyDBInfo:shindyInfo inManagedObjectContext:document.managedObjectContext];
        }
        [document saveToURL:document.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL];
    });
}

- (void)setShindyDatabase:(UIManagedDocument *)shindyDatabase
{
    if (_shindyDatabase != shindyDatabase) {
        _shindyDatabase = shindyDatabase;
        [self useDocument];
    }
}

- (void)useDocument
{
    NSError *error = nil;

    if (![[NSFileManager defaultManager] fileExistsAtPath:[self.shindyDatabase.fileURL path]]) {
        NSLog(@"Create document");
        [self.shindyDatabase saveToURL:self.shindyDatabase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
            [self setupFetchedResultsController];
            [self fetchShindyDataIntoDocument:self.shindyDatabase];

            if (!success) {
                NSLog(@"error for creation of document: %@", [error localizedDescription]);
            }
        }];
    } else if (self.shindyDatabase.documentState == UIDocumentStateClosed) {
        NSLog(@"Closed document");
        [self.shindyDatabase.managedObjectContext.parentContext performBlock:^{
            [self setupFetchedResultsController];
        }];
    } else if (self.shindyDatabase.documentState == UIDocumentStateNormal) {
        NSLog(@"Normal Document");
        [self setupFetchedResultsController];
    }

    if (error) {
        NSLog(@"Error in useDocument: %@", [error localizedDescription]);
    }
}

- (void)setupFetchedResultsController
{
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Shindy"];
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"details" ascending:YES];
    request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
    // request.predicate = [NSPredicate predicateWithFormat:@"details = %@", [self.shindyDatabase valueForKey:@"details"]];
    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                                            managedObjectContext:self.shindyDatabase.managedObjectContext
                                                                              sectionNameKeyPath:nil
                                                                                    cacheName:nil];
}

#pragma mark - Table view data source

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 75;
}

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

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
    }

    Shindy *shindy = [self.fetchedResultsController objectAtIndexPath:indexPath];
    NSLog(@"%@", shindy.details);
    cell.textLabel.text = shindy.details;

Shindy+CreateDB.m

+ (Shindy *)shindyWithShindyDBInfo:(NSDictionary *)shindyInfo
            inManagedObjectContext:(NSManagedObjectContext *)context
{
    Shindy *shindy = nil;

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Shindy"];

    // NSSortDescriptor *dateAndTimeSort = [NSSortDescriptor sortDescriptorWithKey:@"dateAndTime" ascending:YES];
    NSSortDescriptor *detailsSort = [NSSortDescriptor sortDescriptorWithKey:@"details" ascending:YES];
    // NSSortDescriptor *locationSort = [NSSortDescriptor sortDescriptorWithKey:@"location" ascending:YES];
    // NSSortDescriptor *nameSort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
    // NSSortDescriptor *photoSort = [NSSortDescriptor sortDescriptorWithKey:@"photo" ascending:YES];
    // NSSortDescriptor *timePostedSort = [NSSortDescriptor sortDescriptorWithKey:@"timePosted" ascending:YES];
    // title
    request.sortDescriptors = [NSArray arrayWithObject:detailsSort];
    // request.sortDescriptors = [NSArray arrayWithObjects:dateAndTimeSort, detailsSort, locationSort, nameSort, photoSort, timePostedSort, nil];

    NSError *error = nil;
    NSArray *matches = [context executeFetchRequest:request error:&error];

    if (error) {
        NSLog(@"document failed in file: %@", [error localizedDescription]);
    }

    if (!matches || ([matches count] > 1)) {
        NSError *error = nil;
        NSLog(@"error in DBInfo: %@", [error localizedDescription]);
    } else if ([matches count] == 0) {
        shindy = [NSEntityDescription insertNewObjectForEntityForName:@"Shindy" inManagedObjectContext:context];

        // shindy.dateAndTime = [shindyInfo objectForKey:@"dateAndTime"];
        shindy.details = [shindyInfo objectForKey:@"details"];
        // shindy.location = [shindyInfo objectForKey:@"location"];
        // shindy.name = [shindyInfo objectForKey:@"name"];
        // shindy.photo = [shindyInfo objectForKey:@"photo"];
        // shindy.timePosted = [shindyInfo objectForKey:@"timePosted"];
        // title
        // Guestlist? The rest?
        // Use below for reference
        // shindy.whoseShindy = [User userWithName:[shindyInfo objectForKey:@"whoseShindy"] inManagedObjectContext:context];
    } else {
        shindy = [matches lastObject];
    }

    return shindy;
}

编辑:

我想我还应该显示一个我设置为我的子类的文件HomeViewController。它与提供给您粘贴到 Apple 文档中的代码基本相同

CoreDataTableViewController.h

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

@interface CoreDataTableViewController : UITableViewController <NSFetchedResultsControllerDelegate>

@property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;

- (void)performFetch;

@property (nonatomic) BOOL suspendAutomaticTrackingOfChangesInManagedObjectContext;

@property BOOL debug;

@end

CoreDataTableViewController.m

@interface CoreDataTableViewController()
@property (nonatomic) BOOL beganUpdates;
@end

@implementation CoreDataTableViewController

#pragma mark - Properties

@synthesize fetchedResultsController = _fetchedResultsController;
@synthesize suspendAutomaticTrackingOfChangesInManagedObjectContext = _suspendAutomaticTrackingOfChangesInManagedObjectContext;
@synthesize debug = _debug;
@synthesize beganUpdates = _beganUpdates;

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}

#pragma mark - Fetching

- (void)performFetch
{
    if (self.fetchedResultsController) {
        if (self.fetchedResultsController.fetchRequest.predicate) {
            if (self.debug) NSLog(@"[%@ %@] fetching %@ with predicate: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName, self.fetchedResultsController.fetchRequest.predicate);
        } else {
            if (self.debug) NSLog(@"[%@ %@] fetching all %@ (i.e., no predicate)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName);
        }
        NSError *error;
        [self.fetchedResultsController performFetch:&error];
        if (error) NSLog(@"[%@ %@] %@ (%@)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), [error localizedDescription], [error localizedFailureReason]);
    } else {
        if (self.debug) NSLog(@"[%@ %@] no NSFetchedResultsController (yet?)", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
    }
    [self.tableView reloadData];
}

- (void)setFetchedResultsController:(NSFetchedResultsController *)newfrc
{
    NSFetchedResultsController *oldfrc = _fetchedResultsController;
    if (newfrc != oldfrc) {
        _fetchedResultsController = newfrc;
        newfrc.delegate = self;
        if ((!self.title || [self.title isEqualToString:oldfrc.fetchRequest.entity.name]) && (!self.navigationController || !self.navigationItem.title)) {
            self.title = newfrc.fetchRequest.entity.name;
        }
        if (newfrc) {
            if (self.debug) NSLog(@"[%@ %@] %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), oldfrc ? @"updated" : @"set");
            [self performFetch]; 
        } else {
            if (self.debug) NSLog(@"[%@ %@] reset to nil", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
            [self.tableView reloadData];
        }
    }
}

#pragma mark - UITableViewDataSource

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    return [[[self.fetchedResultsController sections] objectAtIndex:section] name];
}

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
    return [self.fetchedResultsController sectionForSectionIndexTitle:title atIndex:index];
}

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
    return [self.fetchedResultsController sectionIndexTitles];
}

#pragma mark - NSFetchedResultsControllerDelegate

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
    if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext) {
        [self.tableView beginUpdates];
        self.beganUpdates = YES;
    }
}

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

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


- (void)controller:(NSFetchedResultsController *)controller
   didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath
     forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{       
    if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext)
    {
        switch(type)
        {
            case NSFetchedResultsChangeInsert:
                [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
                break;

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

            case NSFetchedResultsChangeUpdate:
                [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                break;

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

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

- (void)endSuspensionOfUpdatesDueToContextChanges
{
    _suspendAutomaticTrackingOfChangesInManagedObjectContext = NO;
}

- (void)setSuspendAutomaticTrackingOfChangesInManagedObjectContext:(BOOL)suspend
{
    if (suspend) {
        _suspendAutomaticTrackingOfChangesInManagedObjectContext = YES;
    } else {
        [self performSelector:@selector(endSuspensionOfUpdatesDueToContextChanges) withObject:0 afterDelay:0];
    }
}

@end

最后,但并非最不重要的是,我有我实现 CoreDataTableViewController 的 HomeViewController 的头文件。希望这有助于更好地解释我所拥有的。

HomeViewController.h

#import <UIKit/UIKit.h>
#import <FacebookSDK/FacebookSDK.h>
#import "CoreDataTableViewController.h"

@interface HomeViewController : CoreDataTableViewController

@property (strong, nonatomic) UIManagedDocument *shindyDatabase;
@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;

@end
4

2 回答 2

1

很难看到发生了什么,但是,我认为你需要在块完成后执行以下步骤(我想这是因为我在你的代码中没有看到任何类似的东西)。

  • 通过 fetched 控制器执行 fetch 请求
  • 重新加载数据表

所以,

NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
    // error handling here...
}

[yourTable reloadData];

试着让我知道。如果不起作用,请尝试编辑一个最小问题,因为要遵循的代码太多。

希望有帮助。

于 2012-12-27T09:02:51.550 回答
1

我最终弄清楚了这一点,以及我遇到的许多其他核心数据问题。我没有将我的托管对象上下文设置为商店!呃!!!

self.managedObjectContext = [(AppDelegate *)[UIApplication sharedApplication].delegate managedObjectContext];

那成功了。在那之后一切都开始工作了。

我希望这能够向那些忘记我做过的同样事情的人指出另一个问题!

于 2013-01-26T13:24:12.410 回答