核心数据NSFetchedResultsController抛出NSObjectInaccessibleException

时间:2012-11-13 13:21:33

标签: iphone objective-c ios core-data nsfetchedresultscontroller

我开始使用核心数据。 我正在尝试使用UISearchDisplayController实现NSFetchedResultsController,它将在调用viewWillAppear:方法后在后台尝试更新服务器中的数据。

这是我的核心数据助手实现:

#import <Foundation/Foundation.h>

@interface NEDatabase : NSObject
{
    //
}

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;


+(NEDatabase *)sharedDatabase;

-(void)contextSaved:(NSNotification *)notification;


@end


#import "NEDatabase.h"

#define DEFINE_SHARED_INSTANCE_USING_BLOCK(block) \
static dispatch_once_t pred = 0; \
__strong static id _sharedObject = nil; \
dispatch_once(&pred, ^{ \
_sharedObject = block(); \
}); \
return _sharedObject; \

@implementation NEDatabase

@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;

#pragma mark -
#pragma mark - Singletone implementation

+(NEDatabase *)sharedDatabase
{
    DEFINE_SHARED_INSTANCE_USING_BLOCK(^{
        return [[self alloc] init];
    });
}

-(id)init
{
    self = [super init];
    if (self != nil)
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
        //[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextSaved:) name:NSManagedObjectContextDidSaveNotification object:nil];
    };

    return self;
}


#pragma mark - multi-context handling

-(void)contextSaved:(NSNotification *)notification
{
    NSLog(@"contextSaved: called");

    NSManagedObjectContext *theContext = notification.object;
    if(theContext != [self managedObjectContext])
    {
        NSLog(@"---- BACKGROUND CONTEXT CHANGED");

        [[self managedObjectContext] mergeChangesFromContextDidSaveNotification:notification];
    };
}

#pragma mark - core data

- (void)saveContext
{
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&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();
        }
    }
}

// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
        [_managedObjectContext setStalenessInterval:0];
    }
    return _managedObjectContext;
}

// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
    if (_managedObjectModel != nil) {
        return _managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"nightexpress" withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"nightexpress.sqlite"];

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
         [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]

         * Performing automatic lightweight migration by passing the following dictionary as the options parameter:
         @{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}

         Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.

         */
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _persistentStoreCoordinator;
}

#pragma mark - Application's Documents directory

// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}




@end

和我的表视图控制器(带有搜索显示控制器的获取结果控制器)实现:

#import <UIKit/UIKit.h>
#import "CDDirection.h"
#import "NEDirection.h"
#import "NEDefaults.h"
#import "NEDirectionDelegate.h"
#import "NEServer.h"

@interface NEDirectionViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, NEServerDelegate,UISearchBarDelegate, NSFetchedResultsControllerDelegate, UISearchDisplayDelegate>
{
    IBOutlet UITableView *directionsTableView;
    IBOutlet UITableViewCell *directionCell;

    IBOutlet UISearchDisplayController *searchDisplayController;
    IBOutlet UISearchBar *searchBar;

    NSFetchedResultsController *fetchedResultsController;
    NSFetchedResultsController *searchFetchedResultsController;
    NSManagedObjectContext *context;


    NEDirection *selectedDirection;

    BOOL isFromDirection;

    __unsafe_unretained id<NEDirectionDelegate> delegate;
}

@property (nonatomic, retain) IBOutlet UITableView *directionsTableView;
@property (nonatomic, retain) IBOutlet UITableViewCell *directionCell;

@property (nonatomic, retain) IBOutlet UISearchDisplayController *searchDisplayController;
@property (nonatomic, retain) IBOutlet UISearchBar *searchBar;

@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
@property (nonatomic, retain) NSFetchedResultsController *searchFetchedResultsController;
@property (nonatomic, retain) NSManagedObjectContext *context;

@property (nonatomic, retain) NEDirection *selectedDirection;

@property (nonatomic, readwrite) BOOL isFromDirection;

@property (nonatomic, assign) id<NEDirectionDelegate> delegate;

-(void)updateDirectionsFromServer;

@end

第二部分:

//
//  NEDirectionViewController.m
//  nightexpress
//
//  Created by Oleg Samoylenko on 11/5/12.
//  Copyright (c) 2012 Trinetix. All rights reserved.
//

#import "NEDirectionViewController.h"

@interface NEDirectionViewController ()

@end

@implementation NEDirectionViewController

@synthesize directionsTableView;
@synthesize directionCell;

@synthesize searchDisplayController;
@synthesize searchBar;

@synthesize fetchedResultsController;
@synthesize searchFetchedResultsController;
@synthesize context;

@synthesize selectedDirection;
@synthesize isFromDirection;
@synthesize delegate;

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

- (void)viewDidLoad
{
    NSLog(@"\n\nNEDirectionViewController: viewDidLoad called");
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    self.context=[[NEDatabase sharedDatabase] managedObjectContext];
    [self.context setStalenessInterval:0];

    [self.directionsTableView reloadData];
}

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

-(void)viewWillAppear:(BOOL)animated
{
    NSLog(@"NEDirectionViewController: viewWillAppear: called");
    [super viewWillAppear:animated];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextSaved:) name:NSManagedObjectContextDidSaveNotification object:nil];
    [self updateDirectionsFromServer];
}

-(void)viewWillDisappear:(BOOL)animated
{
    NSLog(@"NEDirectionViewController: viewWillDisappear: called");
    [super viewWillDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [NEServer sharedServer].delegate=nil;
}

#pragma mark - Actions

-(void)contextSaved:(NSNotification *)notification
{
    NSLog(@"contextSaved: called");
    NSManagedObjectContext *theContext = notification.object;
    if(theContext != self.context)
    {
        NSLog(@"---- BACKGROUND CONTEXT CHANGED");

        // should I notify NSFetchedResultsController that there were context saves on background threads?
        // how can I merge contexts if userInfo is nil?
        [self.context mergeChangesFromContextDidSaveNotification:notification];
        [self.directionsTableView reloadData];
    };
}

-(void)updateDirectionsFromServer
{
    NSLog(@"updateDirectionsFromServer called");
    [NEServer sharedServer].delegate=self;
    [[NEServer sharedServer] performSelectorInBackground:@selector(updateDirectionsWithArgs:) withObject:nil];
}


#pragma mark - Helper methods

- (NSFetchedResultsController *)fetchedResultsControllerForTableView:(UITableView *)tableView
{
    NSLog(@"fetchedResultsControllerForTableView: called");
    return tableView == self.directionsTableView ? self.fetchedResultsController : self.searchFetchedResultsController;
}

- (void)fetchedResultsController:(NSFetchedResultsController *)aFetchedResultsController configureCell:(UITableViewCell *)theCell atIndexPath:(NSIndexPath *)theIndexPath
{
    NSLog(@"fetchedResultsController: configureCell: atIndexPath: %i %i", theIndexPath.section, theIndexPath.row);

    NSManagedObjectContext *managedObj=[aFetchedResultsController objectAtIndexPath:theIndexPath];
    if (managedObj==nil)
    {
        NSLog(@"PANIC: fetchedResultsController objectAtIndexPath: returned nil object");
        return;
    }
    else
    {
        CDDirection *dir=(CDDirection *)managedObj;
        UILabel *nameLabel=(UILabel *)[theCell viewWithTag:1];
        [nameLabel setText:dir.name];


        if ([dir.current boolValue]==YES)
        {
            UIImageView *curCityImageView=(UIImageView *)[theCell viewWithTag:2];
            [curCityImageView setImage:[UIImage imageNamed:@"uitableviewcell_accessory1.jpg"]];
        };
        if ([selectedDirection.name isEqualToString:dir.name])
        {
            UIImageView *accImageView=[[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 24, 24)];
            [accImageView setImage:[UIImage imageNamed:@"uitableviewcell_accessory2.png"]];
            [theCell setAccessoryView:accImageView];
        };
   };
}

#pragma mark - UITableViewDataSource

-(UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)theIndexPath
{
    NSLog(@"tableView: cellForRowAtIndexPath: %i %i", theIndexPath.section, theIndexPath.row);

    static NSString *cellIdentifier=@"CellIdentifier";
    UITableViewCell *cell = [theTableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil)
    {
        [[NSBundle mainBundle] loadNibNamed:@"DirectionCell" owner:self options:nil];
        cell=self.directionCell;
        self.directionCell=nil;
    };

    [self fetchedResultsController:[self fetchedResultsControllerForTableView:theTableView] configureCell:cell atIndexPath:theIndexPath];
    return cell;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    NSInteger count = [[[self fetchedResultsControllerForTableView:tableView] sections] count];
    NSLog(@"numberOfSectionsInTableView: %i", count);
    return count;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    NSInteger numberOfRows = 0;
    NSFetchedResultsController *fetchController = [self fetchedResultsControllerForTableView:tableView];
    NSArray *sections = fetchController.sections;
    if(sections.count > 0)
    {
        id <NSFetchedResultsSectionInfo> sectionInfo = [sections objectAtIndex:section];
        numberOfRows = [sectionInfo numberOfObjects];
    };
    NSLog(@"tableView: numberOfRowsInSection: %i", numberOfRows);
    return numberOfRows;
}

#pragma mark - UITableViewDelegate

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"tableView: didSelectRowAtIndexPath: %i %i", indexPath.section, indexPath.row);

    CDDirection *cdDir=[[self fetchedResultsControllerForTableView:tableView] objectAtIndexPath:indexPath];
    self.selectedDirection=[[NEDirection alloc] init];
    self.selectedDirection.name=cdDir.name;
    self.selectedDirection.latitude=cdDir.latitude;
    self.selectedDirection.longitude=cdDir.longitude;
    self.selectedDirection.server_id=cdDir.server_id;
    self.selectedDirection.current=cdDir.current;
    if (isFromDirection)
    {
        [delegate directionUpdatedTo:self.selectedDirection withHeading:@"from"];
    }
    else
    {
        [delegate directionUpdatedTo:self.selectedDirection withHeading:@"to"];
    };
    [tableView reloadData];
    [self.directionsTableView reloadData];
}



#pragma mark - content filtering

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSInteger)scope
{
    // update the filter, in this case just blow away the FRC and let lazy evaluation create another with the relevant search info
    self.searchFetchedResultsController.delegate = nil;
    self.searchFetchedResultsController = nil;
    // if you care about the scope save off the index to be used by the searchFetchedResultsController
    //self.savedScopeButtonIndex = scope;
}


#pragma mark - search bar

- (void)searchDisplayController:(UISearchDisplayController *)controller willUnloadSearchResultsTableView:(UITableView *)tableView;
{
    // search is done so get rid of the search FRC and reclaim memory
    self.searchFetchedResultsController.delegate = nil;
    self.searchFetchedResultsController = nil;
}

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
    [self filterContentForSearchText:searchString scope:[self.searchDisplayController.searchBar selectedScopeButtonIndex]];

    // Return YES to cause the search result table view to be reloaded.
    return YES;
}


- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
    [self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:[self.searchDisplayController.searchBar selectedScopeButtonIndex]];

    // Return YES to cause the search result table view to be reloaded.
    return YES;
}

#pragma mark - NSFetchedResultsControllerDelegate

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
    UITableView *tableView = controller == self.fetchedResultsController ? self.directionsTableView : self.searchDisplayController.searchResultsTableView;
    [tableView beginUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller
  didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex
     forChangeType:(NSFetchedResultsChangeType)type
{
    UITableView *tableView = controller == self.fetchedResultsController ? self.directionsTableView : self.searchDisplayController.searchResultsTableView;

    switch(type)
    {
        case NSFetchedResultsChangeInsert:
            [tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

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


- (void)controller:(NSFetchedResultsController *)controller
   didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)theIndexPath
     forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{
    UITableView *tableView = controller == self.fetchedResultsController ? self.directionsTableView : self.searchDisplayController.searchResultsTableView;

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

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

        case NSFetchedResultsChangeUpdate:
            [self fetchedResultsController:controller configureCell:[tableView cellForRowAtIndexPath:theIndexPath] atIndexPath:theIndexPath];
            break;

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


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    UITableView *tableView = controller == self.fetchedResultsController ? self.directionsTableView : self.searchDisplayController.searchResultsTableView;
    [tableView endUpdates];
}

#pragma mark - FRC creation

- (NSFetchedResultsController *)newFetchedResultsControllerWithSearch:(NSString *)searchString
{
    NSSortDescriptor *sortDescr=[[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)];
    NSArray *sortDescriptors =[NSArray arrayWithObjects:sortDescr, nil];
    NSPredicate *filterPredicate; //= [NSPredicate predicateWithFormat:@"name CONTAINS[cd] %@", searchString];

    /*
     Set up the fetched results controller.
     */
    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *callEntity=[NSEntityDescription entityForName:@"Direction" inManagedObjectContext:self.context];
    [fetchRequest setEntity:callEntity];


    NSMutableArray *predicateArray = [[NSMutableArray alloc] init];
    if(searchString.length)
    {
        // your search predicate(s) are added to this array
        [predicateArray addObject:[NSPredicate predicateWithFormat:@"name CONTAINS[cd] %@", searchString]];
        // finally add the filter predicate for this view
        if(filterPredicate)
        {
            filterPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:filterPredicate, [NSCompoundPredicate orPredicateWithSubpredicates:predicateArray], nil]];
        }
        else
        {
            filterPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:predicateArray];
        }
    };

    [fetchRequest setPredicate:filterPredicate];

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

    [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.context sectionNameKeyPath:nil cacheName:nil];
    aFetchedResultsController.delegate = self;


    NSError *error = nil;
    if (![aFetchedResultsController 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. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
         */
        NSLog(@"Unresolved error %@, %@", [error localizedDescription], [error localizedFailureReason]);
        abort();
    };

    return aFetchedResultsController;
}

- (NSFetchedResultsController *)fetchedResultsController
{
    if (fetchedResultsController != nil)
    {
        return fetchedResultsController;
    };
    fetchedResultsController = [self newFetchedResultsControllerWithSearch:nil];
    return fetchedResultsController;
}

- (NSFetchedResultsController *)searchFetchedResultsController
{
    if (searchFetchedResultsController != nil)
    {
        return searchFetchedResultsController;
    };
    searchFetchedResultsController = [self newFetchedResultsControllerWithSearch:self.searchDisplayController.searchBar.text];
    return searchFetchedResultsController;
}

/*
#pragma mark - UITableViewDelegate

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"tableView: didSelectRow:%i called", indexPath.row);
    if ([tableView isEqual:self.searchDisplayController.searchResultsTableView])
    {
        self.selectedDirection=[self.searchResults objectAtIndex:indexPath.row];
    }
    else
    {
        self.selectedDirection=[self.allItems objectAtIndex:indexPath.row];
    };
    if (isFromDirection)
    {
        if ((delegate!=nil) && ([(UIViewController *)delegate respondsToSelector:@selector(directionUpdatedTo:withHeading:)]))
        {
            [delegate directionUpdatedTo:self.selectedDirection withHeading:@"from"];
        };
    }
    else
    {
        if ((delegate!=nil) && ([(UIViewController *)delegate respondsToSelector:@selector(directionUpdatedTo:withHeading:)]))
        {
            [delegate directionUpdatedTo:self.selectedDirection withHeading:@"to"];
        };
    };
    [self.searchDisplayController.searchResultsTableView reloadData];
    [self.directionsList reloadData];
}
*/

#pragma mark - NEServerDelegate

-(void)directionsUpdateSentAndReceivedResponse:(NSDictionary *)response
{
    NSLog(@"directionsUpdateSentAndReceivedResponse: %@ called", [response debugDescription]);
    //self.context=[[NEDatabase sharedDatabase] managedObjectContext];
    //[self.directionsTableView reloadData];
    //self.searchDisplayController.searchContentsController.
}

@end

我的代码在- (void)fetchedResultsController:(NSFetchedResultsController *)aFetchedResultsController configureCell:(UITableViewCell *)theCell atIndexPath:(NSIndexPath *)theIndexPath

中崩溃了

row:`[nameLabel setText:dir.name];

这是崩溃日志:*** Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0x748d610 <x-coredata://7866ED27-8B71-42CD-A726-3FA14C8B1619/Direction/p2859>''

这是NEServer

-(void)updateDirectionsWithArgs:(NSDictionary *)args
{
    @autoreleasepool
    {
        //... getting data from server and saving it to responseDict NSDictionary

        NSManagedObjectContext *context=[[NSManagedObjectContext alloc] init];
        context.persistentStoreCoordinator=[[NEDatabase sharedDatabase] persistentStoreCoordinator];

        NSFetchRequest *fetchRequest=[[NSFetchRequest alloc] init];
        NSEntityDescription *pEntity=[NSEntityDescription entityForName:@"Direction" inManagedObjectContext:context];
        [fetchRequest setEntity:pEntity];
        NSArray *fetchedResults=[context executeFetchRequest:fetchRequest error:nil];
        for (CDDirection *dir in fetchedResults)
        {
            [context deleteObject:dir];
        };
        [context save:nil];

        NSArray *cities=[responseDict objectForKey:@"cities"];
        for (NSDictionary *dirDict in cities)
        {
            CDDirection *dir=[NSEntityDescription insertNewObjectForEntityForName:@"Direction" inManagedObjectContext:context];
            dir.name=[dirDict objectForKey:@"name"];
            dir.server_id=[dirDict objectForKey:@"id"];
            dir.longitude=[dirDict objectForKey:@"longitude"];
            dir.latitude=[dirDict objectForKey:@"latitude"];
            if ([dir.name isEqualToString:@"Киев"])
            {
                dir.current=[NSNumber numberWithBool:YES];
            }
            else
            {
                dir.current=[NSNumber numberWithBool:NO];
            };
        };
        [context save:nil];

        if ((delegate!=nil) && ([(UIViewController *)delegate respondsToSelector:@selector(directionsUpdateSentAndReceivedResponse:)]))
        {
            [delegate directionsUpdateSentAndReceivedResponse:responseDict];
        };

    }
}

请帮帮我,如何解决这个错误?

P.S。 iOS 4.3+ iphone应用程序