0

私の手順は次のとおりです。

  1. TVCを押します。
  2. 管理オブジェクト コンテキストで新しい FRC を初期化します。
  3. フェッチを実行します。
  4. 各セクションに 1 つの行を持つ 2 つのセクションがあります。
  5. FRCで使用されるフェッチリクエストを実行します。
  6. 2 つの要素を持つ配列を取得しました。
  7. 最後の行を削除し、MOC を保存します。
  8. ポップTVC.
  9. TVCを押します。
  10. 同じ MOC で新しい FRC を開始します。
  11. フェッチを実行します。
  12. 2 つのセクションを取得しました。
  13. FRCで使用されるフェッチリクエストを実行します。
  14. 要素が 1 つの配列を取得しました。

フェッチを実行する前に deleteCacheWithName を呼び出そうとしましたが、成功しませんでした。

何をすべきかわかりません。

クラッシュログ:

2013-01-10 12:27:47.948 MyApp[59830:c07] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[_PFArray objectAtIndex:]: index (1) beyond bounds (1)'

アプリがクラッシュするコード行:

Card *card = [self.fetchedResultsController objectAtIndexPath:indexPath];

以下は、スタンフォード コースの CoreDataTableViewController.m です。

//
//  CoreDataTableViewController.m
//
//  Created for Stanford CS193p Fall 2011.
//  Copyright 2011 Stanford University. All rights reserved.
//

#import "CoreDataTableViewController.h"

@interface CoreDataTableViewController()

@property (nonatomic) BOOL beganUpdates;

@end

@implementation CoreDataTableViewController

#pragma mark - Fetching

- (void)performFetch {
    if (self.fetchedResultsController) {
        NSLog(@"TVC: Perform fetch");

        NSError *error;
        [self.fetchedResultsController performFetch:&error];

        if (error)
            NSLog(@"[%@ %@] %@ (%@)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), [error localizedDescription], [error localizedFailureReason]);

        NSLog(@"TVC: Number of fetched objects in FRC: %d", self.fetchedResultsController.fetchedObjects.count);
        NSLog(@"TVC: Number of sections in FRC: %d", self.fetchedResultsController.sections.count);
    } else {
        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) {
            [self performFetch];
        } else {
            [self.tableView reloadData];
        }
    }
}

#pragma mark - UITableViewDataSource

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    NSUInteger numberOfSections = self.fetchedResultsController.sections.count;
    NSLog(@"TVC: DataSource, number of sections: %d", numberOfSections);

    return numberOfSections;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSArray *sections = self.fetchedResultsController.sections;
    if (sections.count == 0) {
        NSLog(@"TVC: DataSource, there are no sections");
        return 0;
    }

    id<NSFetchedResultsSectionInfo> sectionInfo = [sections objectAtIndex:section];
    NSUInteger numberOfRows = sectionInfo.numberOfObjects;
    NSLog(@"TVC: DataSource, number of rows: %d, in section: %d", numberOfRows, section);

    return numberOfRows;
}
- (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];
    }
}

- (void)logFetchedSections:(NSArray *)sections {
}

@end

ここに私のモデルの一部があります:

//
//  TLModel.m
//

...

@property (nonatomic, strong) TLCoreData *coreData;

...


- (void)setupFetchedResultsControllerCardsListWithCompletion:(void (^)(NSFetchedResultsController *result))completion {
    [self.coreData performWithDocument:^(UIManagedDocument *document) {
        NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Card"];
        request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"named"
                                                                                         ascending:YES
                                                                                          selector:@selector(localizedCaseInsensitiveCompare:)]];
        NSError *error;
        NSArray *matches = [document.managedObjectContext executeFetchRequest:request error:&error];
        NSLog(@"Model: Execute fetch request, array count: %d", matches.count);

        NSFetchedResultsController *result = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                                                 managedObjectContext:document.managedObjectContext
                                                                                   sectionNameKeyPath:@"named"
                                                                                            cacheName:nil];
        NSLog(@"Model: Created new FRC: %@", result);

        completion(result);
    }];
}

...

ここにTVCがあります:

//
//  TLMyTableViewController.m
//

...


- (void)prepareFetchedResultController {
    [self.model setupFetchedResultsControllerCardsListWithCompletion:^(NSFetchedResultsController *result){
        self.fetchedResultsController = result;
    }];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"My Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    // Configure the cell...
    Card *card = [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = card.number;
    cell.detailTextLabel.text = card.option;

    return cell;
}
- (void)viewDidLoad {
    NSLog(@"TVC: Did load: %@", self);
    [self prepareFetchedResultController];
}

...

TLコアデータ:

//
//  TLCoreData.m
//

#import "TLCoreData.h"
#import <CoreData/CoreData.h>
#import "TLManagedDocument.h"

@interface TLCoreData()

@property (nonatomic, strong) TLManagedDocument *document;

@end

@implementation TLCoreData

/*
static TLCoreData *_sharedInstance;

+ (TLCoreData *)sharedDocumentHandler {
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        _sharedInstance = [[self alloc] init];
    });

    return _sharedInstance;
}
*/

- (TLManagedDocument *)document {
    if (!_document) {
        NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
        url = [url URLByAppendingPathComponent:@"DataUsage.db"];
        _document = [[TLManagedDocument alloc] initWithFileURL:url];
    }

    return _document;
}

- (void)performWithDocument:(OnDocumentReady)onDocumentReady {
    void (^OnDocumentDidLoad)(BOOL) = ^(BOOL success) {
        if(success) {
#ifdef DEBUG
            NSLog(@"Current context: %@", self.document.managedObjectContext);
#endif
            onDocumentReady(self.document);
        }
#ifdef DEBUG
        else
            NSLog(@"Core Data: Managed document does not ready");
#endif
    };

    if (![[NSFileManager defaultManager] fileExistsAtPath:[self.document.fileURL path]]) {
#ifdef DEBUG
        NSLog(@"Core Data: Initialized document: %@", self.document.fileURL);
#endif
        [self.document saveToURL:self.document.fileURL
                forSaveOperation:UIDocumentSaveForCreating
               completionHandler:OnDocumentDidLoad];
    } else if (self.document.documentState == UIDocumentStateClosed) {
#ifdef DEBUG
        NSLog(@"Core Data: Opened document: %@", self.document.fileURL);
#endif
        [self.document openWithCompletionHandler:OnDocumentDidLoad];
    } else if (self.document.documentState == UIDocumentStateNormal) {
        OnDocumentDidLoad(YES);
    }
}

- (void)objectsDidChange:(NSNotification *)notification {
#ifdef DEBUG
    NSLog(@"Core Data: Objects changed in context: %@", self.document.managedObjectContext);
#endif
}
- (void)contextDidSave:(NSNotification *)notification {
#ifdef DEBUG
    NSLog(@"Core Data: Context saved: %@", self.document.managedObjectContext);
#endif
}

- (id)init {
    self = [super init];
    if (self) {

        // Set our document up for automatic migrations
        NSDictionary *options = @{
            NSMigratePersistentStoresAutomaticallyOption : @YES,
            NSInferMappingModelAutomaticallyOption : @YES
        };
        self.document.persistentStoreOptions = options;

        // Register for notifications
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(objectsDidChange:)
                                                     name:NSManagedObjectContextObjectsDidChangeNotification
                                                   object:self.document.managedObjectContext];

        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(contextDidSave:)
                                                     name:NSManagedObjectContextDidSaveNotification
                                                   object:self.document.managedObjectContext];
    }

    return self;
}
- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:NSManagedObjectContextDidSaveNotification
                                                  object:self.document.managedObjectContext];

    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:NSManagedObjectContextObjectsDidChangeNotification
                                                  object:self.document.managedObjectContext];
}

@end

ログは次のとおりです。

2013-01-10 12:27:43.291 MyApp[59830:c07] App: Launched
2013-01-10 12:27:43.354 MyApp[59830:c07] Core Data: Opened document: file://localhost/Users/itsme/Library/Application%20Support/iPhone%20Simulator/6.0/Applications/998028DF-FACC-4EFF-A5C7-B286B91F1100/Documents/DataUsage.db/
2013-01-10 12:27:43.354 MyApp[59830:c07] Model: Logging started
2013-01-10 12:27:43.357 MyApp[59830:c07] App: Did become active
2013-01-10 12:27:43.371 MyApp[59830:c07] Current context: <NSManagedObjectContext: 0x8185590>
2013-01-10 12:27:43.374 MyApp[59830:c07] Current context: <NSManagedObjectContext: 0x8185590>
2013-01-10 12:27:44.746 MyApp[59830:c07] TVC: Did load: <TLMyTableViewController: 0x8566100>
2013-01-10 12:27:44.746 MyApp[59830:c07] Current context: <NSManagedObjectContext: 0x8185590>
2013-01-10 12:27:44.747 MyApp[59830:c07] Model: Execute fetch request, array count: 2
2013-01-10 12:27:44.748 MyApp[59830:c07] Model: Created new FRC: <NSFetchedResultsController: 0x747bbb0>
2013-01-10 12:27:44.748 MyApp[59830:c07] TVC: Perform fetch
2013-01-10 12:27:44.750 MyApp[59830:c07] TVC: Number of fetched objects in FRC: 2
2013-01-10 12:27:44.750 MyApp[59830:c07] TVC: Number of sections in FRC: 2
2013-01-10 12:27:44.751 MyApp[59830:c07] TVC: DataSource, number of sections: 2
2013-01-10 12:27:44.752 MyApp[59830:c07] TVC: DataSource, number of rows: 1, in section: 1
2013-01-10 12:27:44.752 MyApp[59830:c07] TVC: DataSource, number of rows: 1, in section: 0
2013-01-10 12:27:46.346 MyApp[59830:c07] Current context: <NSManagedObjectContext: 0x8185590>
2013-01-10 12:27:46.347 MyApp[59830:c07] Model: Deleting a row
2013-01-10 12:27:46.349 MyApp[59830:c07] TVC: DataSource, number of sections: 1
2013-01-10 12:27:46.349 MyApp[59830:c07] TVC: DataSource, number of sections: 1
2013-01-10 12:27:46.349 MyApp[59830:c07] TVC: DataSource, number of rows: 1, in section: 0
2013-01-10 12:27:46.350 MyApp[59830:c07] Core Data: Objects changed in context: <NSManagedObjectContext: 0x8185590>
2013-01-10 12:27:46.351 MyApp[59830:c07] Core Data: Context saved: <NSManagedObjectContext: 0x8185590>
2013-01-10 12:27:47.941 MyApp[59830:c07] TVC: Did load: <TLMyTableViewController: 0x747d5e0>
2013-01-10 12:27:47.941 MyApp[59830:c07] Current context: <NSManagedObjectContext: 0x8185590>
2013-01-10 12:27:47.942 MyApp[59830:c07] Model: Execute fetch request, array count: 1
2013-01-10 12:27:47.942 MyApp[59830:c07] Model: Created new FRC: <NSFetchedResultsController: 0x74b9410>
2013-01-10 12:27:47.942 MyApp[59830:c07] TVC: Perform fetch
2013-01-10 12:27:47.944 MyApp[59830:c07] TVC: Number of fetched objects in FRC: 1
2013-01-10 12:27:47.944 MyApp[59830:c07] TVC: Number of sections in FRC: 2
2013-01-10 12:27:47.944 MyApp[59830:c07] TVC: DataSource, number of sections: 2
2013-01-10 12:27:47.945 MyApp[59830:c07] TVC: DataSource, number of rows: 1, in section: 1
2013-01-10 12:27:47.945 MyApp[59830:c07] TVC: DataSource, number of rows: 1, in section: 0
2013-01-10 12:27:47.948 MyApp[59830:c07] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[_PFArray objectAtIndex:]: index (1) beyond bounds (1)'

この行は、配列内のセクションの数が間違っていることを示しています。

2013-01-10 12:27:47.944 MyApp[59830:c07] TVC: Number of sections in FRC: 2

このログのソース コード:

NSLog(@"TVC: Number of sections in FRC: %d", self.fetchedResultsController.sections.count);
4

1 に答える 1

0

あなたは私たちに他の詳細を提供する必要があります。

それまでの間、クラスをご覧になることをお勧めしますNSFetchedResultsControllerDelegate。実装する必要のあるメソッドは、クラスリファレンスにあります。

NSFetchedResultsControllerインスタンスのデリゲートを次のように設定した場合

_fetchedController.delegate = self;

次に、デリゲートはコアデータモデルに加えられた変更に応答します(セクションの追加または削除、行の追加、削除、移動、または更新)。

たとえば、

- (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];
            break;
    }
}

セクションを削除または追加すると、変更がキャプチャされます。

それが役に立てば幸い。

編集

私の推測では、TLMyTableViewControllerextendsCoreDataTableViewControllerの場合、で正しいメソッドを呼び出していません

- (void)prepareFetchedResultController {
    [self.model setupFetchedResultsControllerCardsListWithCompletion:^(NSFetchedResultsController *result){
        self.fetchedResultsController = result;
    }];
}

代わりに使用してみてください

[self setFetchedResultsController:result];
于 2013-01-10T09:29:42.533 に答える