使用两个独立的数据模型与coredata?

时间:2016-08-11 09:12:28

标签: ios objective-c sqlite core-data model

在我的应用程序中,我使用sqlite数据库和核心数据来显示数据库中的数据,一切正常。 我希望用户能够在app的文档目录中添加照片,所以我为app定义了两个模型。

我使用了这个链接http://blog.atwam.com/blog/2012/05/11/multiple-persistent-stores-and-seed-data-with-core-data/ 以及来自Apple示例代码(https://developer.apple.com/library/ios/samplecode/PhotoLocations/Introduction/Intro.html)的PhotoLocations,用于添加照片功能。

从sql显示数据很好但是当我向app添加另一个模型并操纵AppDelegate时,应用程序崩溃了。

我不想使用MagicalRecord,因为我对核心数据的支持已超过一半。

这是我原来的AppDelegate:

        //  AppDelegate.m
    //  iranbirds
    //
    //  Created by Mehdi on 7/31/16.
    //  Copyright © 2016 Mehdi. All rights reserved.
    //

    #import "AppDelegate.h"
    #import "BirdsTableViewController.h"
    #import "GeneralViewController.h"
    #import "FavoriteTableViewController.h"
    #import "MapViewController.h"
    #import "MoreViewController.h"
    //#import "Bird.h"                                  //maybe delete
    #import "BirdInfo.h"
    #import "BirdImage.h"
    #import "Favorite.h"
    #import <CoreData/CoreData.h>

    @interface AppDelegate ()   //class extension
    @property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
    @property (nonatomic, strong) NSManagedObjectModel *managedObjectModel;
    @property (nonatomic, strong) NSPersistentStoreCoordinator *persistentStoreCoordinator;
    @property (nonatomic, strong) NSArray *fetchedObjects;


    @end


        @implementation AppDelegate

        - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
      { 

            - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{


    UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;




    UINavigationController *naviController = (UINavigationController *)tabBarController.viewControllers[0];
    naviController = (UINavigationController *)tabBarController.viewControllers[0];
    BirdsTableViewController *catalogViewController = (BirdsTableViewController *)[naviController topViewController];
    //  catalogViewController.managedojbectContext = self.managedObjectContext;






    //pass managed context to species view controller
    naviController = (UINavigationController *)tabBarController.viewControllers[0];
    MapViewController *mapViewController = (MapViewController *)[naviController topViewController];
    mapViewController.managedOjbectContext = self.managedObjectContext;



    naviController = (UINavigationController *)tabBarController.viewControllers[0];
    FavoriteTableViewController *favoriteViewcontroller = (FavoriteTableViewController *)[naviController topViewController];
    favoriteViewcontroller.managedOjbectContext = self.managedObjectContext;



    //pass managed context  view controller
    naviController = (UINavigationController *)tabBarController.viewControllers[0];
    MoreViewController *moreViewController = (MoreViewController *)[naviController topViewController];
    moreViewController.managedOjbectContext = self.managedObjectContext;

    //pass managed context  view controller

    naviController = (UINavigationController *)tabBarController.viewControllers[0];
    APLViewController *aplViewController = (APLViewController *)[naviController topViewController];
    aplViewController.managedOjbectContext = self.managedObjectContext;

            return YES;
        }
        - (void)applicationWillTerminate:(UIApplication *)application {
        }

        #pragma mark - Core Data stack
        - (NSManagedObjectModel *)managedObjectModel {
            if (_managedObjectModel == nil) {
                NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"TaxonModel" ofType:@"mom"];


                NSURL *modelUrl = [NSURL fileURLWithPath:modelPath];
                _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelUrl];
            }
            return _managedObjectModel;
        }

        - (NSString *)documentsDirectory {
            NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
            NSString *documentsDirectory = [paths lastObject];
            //NSLog(@"document directory: %@", documentsDirectory);
            return documentsDirectory;
        }

        - (NSString *)dataStorePath
        {
            return [[self documentsDirectory] stringByAppendingPathComponent:@"DataStore.sqlite"];
        }

        /**
         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;
            }

            if (_persistentStoreCoordinator == nil) {



                //if the expected store doesn't exist, copy the default store from main bundle
                if (![[NSFileManager defaultManager] fileExistsAtPath:[self dataStorePath]]) {
                    NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"DataStore" ofType:@"sqlite"];  // we construct a path to our database file We’re storing the database in our application’s bundle,o we use the pathForResource method to obtain the path.
                    if (defaultStorePath) {
                        [[NSFileManager defaultManager] copyItemAtPath:defaultStorePath toPath:[self dataStorePath] error:NULL];
                    }
                }

                NSURL *storeUrl = [NSURL fileURLWithPath:[self dataStorePath]];




                //   NSURL *storeUrl= [[self applicationDirectory] URLByAppendingPathComponent:@"Card.sqlite"];

                _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];

                NSError *error;
                //NSDictionary *options = @{NSSQLitePragmasOption:@{@"journal_mode":@"DELETE"}};
                if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                               configuration:nil
                                                                         URL:storeUrl
                                                                     options:nil
                                                                       error:&error]) {
                    //NSLog(@"Error adding persistent store %@, %@", error, [error userInfo]);
                    abort();
                }
            }
            [self addSkipBackupAttributeToItemAtPath:[self dataStorePath]];
            return _persistentStoreCoordinator;
        }

        - (BOOL)addSkipBackupAttributeToItemAtPath:(NSString *) filePathString
        {
            NSURL* URL= [NSURL fileURLWithPath:filePathString];
            assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);

            NSError *error = nil;
            BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
                                          forKey: NSURLIsExcludedFromBackupKey error: &error];
            if(!success){
                NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);
            }
            //NSLog(@"Added %@",[NSNumber numberWithBool: success]);
            return success;
        }

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



        - (void)preloadData {
            NSString *path = [[NSBundle mainBundle] pathForResource:@"acachecklist" ofType:@"txt"];
            NSError *error;
            NSString *allBirds = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
            if (allBirds == nil) {
                //NSLog(@"Error reading file: %@",[error localizedDescription]);
            }
            NSArray *lines=[allBirds componentsSeparatedByString:@"\n"];
            unsigned long count = [lines count];
            NSArray *bird;
            for(int i=0;i<count;i++) {
                bird=[[lines objectAtIndex:i] componentsSeparatedByString:@"\t"];

                BirdInfo *info = [NSEntityDescription insertNewObjectForEntityForName:@"BirdInfo"
                                                               inManagedObjectContext:self.managedObjectContext];

                BirdImage *imageObj = [NSEntityDescription insertNewObjectForEntityForName:@"BirdImage"
                                                                    inManagedObjectContext:self.managedObjectContext];

                UIImage *tempImage = [UIImage imageNamed:@"Placeholder"];
                imageObj.image = UIImageJPEGRepresentation(tempImage,1);

                info.category = [bird objectAtIndex:0];
                info.com_name = [bird objectAtIndex:1];
                info.sci_name = [bird objectAtIndex:2];
                //info.taxon_id = [bird objectAtIndex:2];
                info.thumbnailImage = imageObj;

                NSError *error;
                if (![self.managedObjectContext save:&error]) {
                    //NSLog(@"Error: %@", error);
                    abort();
                }
            }
        }


        - (void)preLoadSpecies
        {
            NSManagedObjectContext *privateContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
            privateContext.persistentStoreCoordinator = self.managedObjectContext.persistentStoreCoordinator;
            NSEntityDescription *entity = [NSEntityDescription insertNewObjectForEntityForName:@"BirdInfo"
                                                                        inManagedObjectContext:self.managedObjectContext];
            NSFetchRequest *allSpeciesRequest = [[NSFetchRequest alloc] init];
            [allSpeciesRequest setEntity:entity];
            [privateContext performBlock:^{
                NSError *error;
                self.fetchedObjects = [privateContext executeFetchRequest:allSpeciesRequest error:&error];
                if (error) {
                    //NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                    abort();
                }
            }];
        }

        @end

编辑后的AppDelegate:

#import "AppDelegate.h"
#import "BirdsTableViewController.h"
#import "GeneralViewController.h"
#import "FavoriteTableViewController.h"
#import "MapViewController.h"
#import "MoreViewController.h"
//#import "Bird.h"                                  //maybe delete
#import "BirdInfo.h"
#import "BirdImage.h"
#import "Favorite.h"
#import <CoreData/CoreData.h>
#import "APLViewController.h"


@interface AppDelegate ()   //class extension
@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, strong) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, strong) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property (nonatomic, strong) NSArray *fetchedObjects;


@end


@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{


    UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;



    UINavigationController *naviController = (UINavigationController *)tabBarController.viewControllers[0];
    naviController = (UINavigationController *)tabBarController.viewControllers[0];
    BirdsTableViewController *catalogViewController = (BirdsTableViewController *)[naviController topViewController];
    //  catalogViewController.managedojbectContext = self.managedObjectContext;


    //pass managed context to species view controller
    naviController = (UINavigationController *)tabBarController.viewControllers[0];
    MapViewController *mapViewController = (MapViewController *)[naviController topViewController];
    mapViewController.managedOjbectContext = self.managedObjectContext;



    naviController = (UINavigationController *)tabBarController.viewControllers[0];
    FavoriteTableViewController *favoriteViewcontroller = (FavoriteTableViewController *)[naviController topViewController];
    favoriteViewcontroller.managedOjbectContext = self.managedObjectContext;

    //pass managed context  view controller

    naviController = (UINavigationController *)tabBarController.viewControllers[0];
    APLViewController *aplViewController = (APLViewController *)[naviController topViewController];
    aplViewController.managedOjbectContext = self.managedObjectContext;


    /* 
     //[self preloadData];   //preload birds info into core data
     //  UITabBarController *tabBarController ;
     UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;

     //pass managed context to first view controller
     UINavigationController *naviController = (UINavigationController *)tabBarController.viewControllers[0];
     BirdsTableViewController *birdsTableViewController = (BirdsTableViewController *)[naviController topViewController];
     birdsTableViewController.managedOjbectContext = self.managedObjectContext;

     //pass managed context to nearby view controller
     naviController = (UINavigationController *)tabBarController.viewControllers[1];
     GeneralViewController *generalViewController = (GeneralViewController *)[naviController topViewController];
     generalViewController.managedOjbectContext = self.managedObjectContext;


     //pass managed context to species view controller
     naviController = (UINavigationController *)tabBarController.viewControllers[2];
     SpeciesViewController *catalogViewController = (SpeciesViewController *)[naviController topViewController];
     catalogViewController.managedOjbectContext = self.managedObjectContext;

     //pass managed context to favorite view controller
     naviController = (UINavigationController *)tabBarController.viewControllers[3];
     FavoritesViewController *favoriteViewcontroller = (FavoritesViewController *)[naviController topViewController];
     favoriteViewcontroller.managedOjbectContext = self.managedObjectContext;



     UIColor* navColor = [UIColor colorWithRed:0.175f green:0.458f blue:0.831f alpha:1.0f];
     [[UINavigationBar appearance] setBarTintColor:navColor];
     [[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];
     [[UINavigationBar appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]}];

     //UIColor *barColor = [UIColor colorWithRed:0.012 green:0.286 blue:0.553 alpha:1.0];
     [tabBarController.tabBar setTintColor:navColor];

     //[self preLoadSpecies];

     [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;

     //set tab bar item selected images;
     NSArray *array = tabBarController.tabBar.items;
     ((UITabBarItem *)array[2]).selectedImage = [UIImage imageNamed:@"Pelican Filled"];
     ((UITabBarItem *)array[0]).selectedImage = [UIImage imageNamed:@"Log Cabin Filled"];
     ((UITabBarItem *)array[1]).selectedImage = [UIImage imageNamed:@"Binoculars Filled"];
     ((UITabBarItem *)array[3]).selectedImage = [UIImage imageNamed:@"Like Filled"];





     //pass managed context to general view controller
     UINavigationController *naviController = (UINavigationController *)tabBarController.viewControllers[0];
     GeneralViewController *Genralviewcontroler = (GeneralViewController *)[naviController topViewController];
     Genralviewcontroler.managedOjbectContext = self.managedObjectContext;




     [window addSubview:_navController.view];
     */


    //set tab bar item selected images;
    NSArray *array = tabBarController.tabBar.items;
    //((UITabBarItem *)array[2]).selectedImage = [UIImage imageNamed:@"Pelican Filled"];
    ((UITabBarItem *)array[0]).selectedImage = [UIImage imageNamed:@"Log Cabin Filled"];
    //((UITabBarItem *)array[1]).selectedImage = [UIImage imageNamed:@"Falcon Filled"];
    ((UITabBarItem *)array[2]).selectedImage = [UIImage imageNamed:@"Like Filled"];



    return YES;
}


- (void)applicationWillTerminate:(UIApplication *)application {
}

#pragma mark - Core Data stack
- (NSManagedObjectModel *)managedObjectModel
{
    if (_managedObjectModel != nil) {
        return _managedObjectModel;
    }
    NSURL *uModelURL = [[NSBundle mainBundle] URLForResource:@"Locations" withExtension:@"momd"];
    NSManagedObjectModel* uModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:uModelURL];

    NSURL *pdModelURL = [[NSBundle mainBundle] URLForResource:@"TaxonModel" withExtension:@"mom"];
    NSManagedObjectModel* pdModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:pdModelURL];

    _managedObjectModel = [NSManagedObjectModel modelByMergingModels:[NSArray arrayWithObjects:uModel, pdModel, nil]];

    return _managedObjectModel;
}


- (NSString *)documentsDirectory {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths lastObject];
    //NSLog(@"document directory: %@", documentsDirectory);
    return documentsDirectory;
}


- (NSString *)dataStorePath
{
    return [[self documentsDirectory] stringByAppendingPathComponent:@"DataStore.sqlite"];
}






/**
 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;
    }

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

    [self addSeedDataToCoordinator:_persistentStoreCoordinator];

    NSURL* userURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"UserData.sqlite"];
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];


    /*
     // Allow inferred migration from the original version of the application.
     NSDictionary *options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES, NSInferMappingModelAutomaticallyOption : @YES };


     */

    // Note that we use our UserConf here
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:@"UserConf" URL:userURL options:nil error:&error])
    {
        NSLog(@"Error %@",error);
    }
    [self addSkipBackupAttributeToItemAtPath:[self dataStorePath]];  // *******i added*******
    return _persistentStoreCoordinator;
}


- (void) addSeedDataToCoordinator:(NSPersistentStoreCoordinator *)storeCoordinator
{
    // Our destination url, writtable. Make sure this is in Library/Cache if you don't want iCloud to backup this.
    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"DataStore.sqlite"];

    NSError *error = nil;   //************ i define
    //NSURL* adURL;//********************i define

    // If we don't have our migrated store, prepare it
    if (![[NSFileManager defaultManager] fileExistsAtPath:[storeURL path]])
    {
        // Our source url should come from a download, but let's use our bundle for debug purposes in the simulator


        NSURL *baseURL = [[NSBundle mainBundle] URLForResource:@"DataStore" withExtension:@"sqlite"];
     //   [[NSFileManager defaultManager] copyItemAtPath:baseURL toPath:[self dataStorePath] error:NULL];  ///######@#@#this line
       // [NSFileManager defaultManager]copyItemAtPath:<#(nonnull NSString *)#> toPath:<#(nonnull NSString *)#> error:NULL];


        [[NSFileManager defaultManager]contentsAtPath:[self dataStorePath]];   // I ADD THIS LINE



        // Create one coordinator that just migrates, but isn't used.
        NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                                 [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                                 [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
                                 nil];

        // This will just handle the migration, without any configuration or else ...
        NSPersistentStore* tmpStore = [storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error];
        // And remove it !
        [storeCoordinator removePersistentStore:tmpStore error:&error];
    }

    // And now add the coordinator with the correct 'PostCodesConf' configuration, in readonly mode
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSReadOnlyPersistentStoreOption, nil];
    [storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:@"PostCodesConf" URL:storeURL options:options error:&error];






}





- (BOOL)addSkipBackupAttributeToItemAtPath:(NSString *) filePathString
{
    NSURL* URL= [NSURL fileURLWithPath:filePathString];
    assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]);

    NSError *error = nil;
    BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES]
                                  forKey: NSURLIsExcludedFromBackupKey error: &error];
    if(!success){
        NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error);
    }
    //NSLog(@"Added %@",[NSNumber numberWithBool: success]);
    return success;
}



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


- (void)preloadData {
    NSString *path = [[NSBundle mainBundle] pathForResource:@"acachecklist" ofType:@"txt"];
    NSError *error;
    NSString *allBirds = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
    if (allBirds == nil) {
        //NSLog(@"Error reading file: %@",[error localizedDescription]);
    }
    NSArray *lines=[allBirds componentsSeparatedByString:@"\n"];
    unsigned long count = [lines count];
    NSArray *bird;
    for(int i=0;i<count;i++) {
        bird=[[lines objectAtIndex:i] componentsSeparatedByString:@"\t"];

        BirdInfo *info = [NSEntityDescription insertNewObjectForEntityForName:@"BirdInfo"
                                                       inManagedObjectContext:self.managedObjectContext];

        BirdImage *imageObj = [NSEntityDescription insertNewObjectForEntityForName:@"BirdImage"
                                                            inManagedObjectContext:self.managedObjectContext];

        UIImage *tempImage = [UIImage imageNamed:@"Placeholder"];
        imageObj.image = UIImageJPEGRepresentation(tempImage,1);

        info.category = [bird objectAtIndex:0];
        info.com_name = [bird objectAtIndex:1];
        info.sci_name = [bird objectAtIndex:2];
        //info.taxon_id = [bird objectAtIndex:2];
        info.thumbnailImage = imageObj;

        NSError *error;
        if (![self.managedObjectContext save:&error]) {
            //NSLog(@"Error: %@", error);
            abort();
        }
    }
}


- (void)preLoadSpecies
{
    NSManagedObjectContext *privateContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    privateContext.persistentStoreCoordinator = self.managedObjectContext.persistentStoreCoordinator;
    NSEntityDescription *entity = [NSEntityDescription insertNewObjectForEntityForName:@"BirdInfo"
                                                                inManagedObjectContext:self.managedObjectContext];
    NSFetchRequest *allSpeciesRequest = [[NSFetchRequest alloc] init];
    [allSpeciesRequest setEntity:entity];
    [privateContext performBlock:^{
        NSError *error;
        self.fetchedObjects = [privateContext executeFetchRequest:allSpeciesRequest error:&error];
        if (error) {
            //NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }];
}

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

当我想在第一个视图控制器中使用以下日志加载数据时,应用程序崩溃:

 Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'BirdInfo''

0 个答案:

没有答案