核心数据到 SQL 不起作用

Posted

技术标签:

【中文标题】核心数据到 SQL 不起作用【英文标题】:Core Data to SQL not working 【发布时间】:2012-12-19 04:50:18 【问题描述】:

我一直在努力弄清楚如何在我的 Core Data 和我的 SQL 数据库之间建立连接。该数据库未预先填充,但在启动时将在许多不同的用户中使用。

我已经上过斯坦福大学提供的 Core Data & iCloud 课程 3 次,但无济于事。我还彻底研究了 ios 中的 SQLite/SQL 关系数据库,但无济于事。我唯一的另一个选择是来到这里,发布我能发布的所有代码,并祈祷有人会为我解答。就这样吧……

AppDelegate.m

- (void)saveContext

    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) 
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) 

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


#pragma mark - Core Data stack

- (NSManagedObjectContext *)managedObjectContext

    if (_managedObjectContext != nil) 
        return _managedObjectContext;
    

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


- (NSManagedObjectModel *)managedObjectModel

    if (_managedObjectModel != nil) 
        return _managedObjectModel;
    
    NSURL *modelURL = [self applicationDocumentsDirectory];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;


- (NSPersistentStoreCoordinator *)persistentStoreCoordinator

    if (_persistentStoreCoordinator != nil) 
        return _persistentStoreCoordinator;
    

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

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

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

    return _persistentStoreCoordinator;


#pragma mark - Application's Documents directory

- (NSURL *)applicationDocumentsDirectory

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"shindy.sqlite"];

    return [NSURL fileURLWithPath:path];

HomeViewController.m

- (void)setupFetchedResultsController

    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Shindy"];
    request.sortDescriptors = [NSArray arrayWithObjects:
                               [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES],
                               [NSSortDescriptor sortDescriptorWithKey:@"dateAndTime" ascending:YES],
                               [NSSortDescriptor sortDescriptorWithKey:@"photo" ascending:YES],
                               [NSSortDescriptor sortDescriptorWithKey:@"details" ascending:YES],
                               [NSSortDescriptor sortDescriptorWithKey:@"timePosted" ascending:YES],
                               [NSSortDescriptor sortDescriptorWithKey:@"location" ascending:YES],
                                                                                                    nil];

    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                                        managedObjectContext:self.shindyDatabase.managedObjectContext
                                                                          sectionNameKeyPath:nil
                                                                                   cacheName:nil];



- (void)fetchShindyDataIntoDocument:(UIManagedDocument *)document

    dispatch_queue_t fetchQ = dispatch_queue_create("Shindy Fetcher", nil);
    dispatch_async(fetchQ, ^
        NSArray *shindys = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
        NSLog(@"shindys = %@", shindys);
        [document.managedObjectContext performBlock:^
            for (NSDictionary *shindyInfo in shindys) 
                [Shindy shindyWithShindyDBInfo:shindyInfo inManagedObjectContext:document.managedObjectContext];
                NSLog(@"fire");
            
        ];
    );


- (void)useDocument

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"shindy.sqlite"];

    if (![[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil]) 
        [self.shindyDatabase saveToURL:self.shindyDatabase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) 
            [self setupFetchedResultsController];
            [self fetchShindyDataIntoDocument:self.shindyDatabase];
        ];
     else if (self.shindyDatabase.documentState == UIDocumentStateClosed) 
            [self.shindyDatabase openWithCompletionHandler:^(BOOL success) 
        [self setupFetchedResultsController];
        ];
     else if (self.shindyDatabase.documentState == UIDocumentStateNormal) 
        [self setupFetchedResultsController];
    


- (void)setShindyDatabase:(UIManagedDocument *)shindyDatabase

    [self useDocument];


- (void)viewWillAppear:(BOOL)animated

    [super viewWillAppear:animated];

    [self fetchShindyDataIntoDocument:self.shindyDatabase];

    if (!self.shindyDatabase) 
        [self setShindyDatabase:self.shindyDatabase];
    

Shindy+ShindyDB.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 arrayWithObjects:dateAndTimeSort, detailsSort, locationSort, nameSort, photoSort, timePostedSort, nil];

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

    if (!matches || ([matches count] > 1)) 
        // handle error
     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];
    

    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"];

    return shindy;

AddShindyViewController.m

- (void)saveShindyToDatabase

    NSArray *shindys = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
    [self.shindyDatabase.managedObjectContext performBlock:^
        for (NSDictionary *shindyInfo in shindys) 
            [Shindy shindyWithShindyDBInfo:shindyInfo inManagedObjectContext:self.shindyDatabase.managedObjectContext];

            NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
            // url = [url URLByAppendingPathComponent:@"Default Shindy Database"];
            self.shindyDatabase = [[UIManagedDocument alloc] initWithFileURL:url];

            [self.shindyDatabase setValue:self.detailView.text forKey:@"details"];

            if (FBSession.activeSession.isOpen) 
                [[FBRequest requestForMe] startWithCompletionHandler:
                    ^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) 
                        if (!error) 
                            self.name = user.name;
                            self.photo.profileID = user.id;
                            self.username = user.username;
                        
                    ];
            
            [self.shindyDatabase setValue:self.name forKey:@"name"];
            [self.shindyDatabase setValue:self.photo forKey:@"photo"];
            [self.shindyDatabase setValue:self.username forKey:@"username"];
            // [Guest guestWithName:self.name username:self.username photo:self.photo inManagedObjectContext:self.shindyDatabase.managedObjectContext];
            [self.shindyDatabase setValue:self.locationManager.location forKey:@"location"];
            [self.shindyDatabase setValue:self.dateAndTimePicker.date forKey:@"dateAndTime"];
        
    ];

我知道我要的东西太多了,但是我已经用尽了我可以使用的每一个资源。如果有人能指出我正确的方向,我将永远感激不尽!

【问题讨论】:

首先,如果你的问题是映射一个现有的数据库,那就算了,你做不到。否则,尝试实现一些错误记录,例如在你写了'//处理错误'的地方尝试添加[错误本地化描述],也放置一些断点并查看是否调用了方法,然后逐步查看它在哪里中断。 【参考方案1】:

如果您打算使用 CoreData 映射现有数据库,您将不会成功。 事实上,您无法使用 CoreData 映射任何数据库。

Core Data 实际上是一个图形对象管理,具有不同的存储选项,而 sqllite 只是其中一种可能性。在启动时,如果您选择 sqllite 作为选项,您的应用程序将创建一个具有特定表结构的数据库。如果您尝试连接到不是由 CoreData 框架创建的数据库,则会出现错误。

您可以做的是摆脱 CoreData,并构建您的 NSObject 以像实体一样工作。但随后,您将不得不实现所有逻辑来保存、更新、版本控制、并发 ecc……这是一个漫长(且有问题)的方式,尤其是在多用户环境中。

否则,如果我误解了您的问题,请告诉我。也许,您可以发布错误堆栈跟踪。

【讨论】:

为了提供准确的报价,developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/… :“重要提示:尽管 Core Data 支持 SQLite 作为存储类型,但存储格式(与其他原生 Core Data 存储一样)是私有的。您无法使用原生 SQLite API 创建 SQLite 数据库并直接与 Core Data 一起使用(也不应该使用原生 SQLite API 操作现有的 Core Data SQLite 存储)。如果您有现有的 SQLite 数据库,则需要将其导入 Core Data存储(参见“高效导入数据”)。” 此外,我想知道为什么这个问题得到了这么多赞成票!在这样一个众所周知的主题上。 我已经明白你所说的了。我发布了我的代码,因为据我所知,我已经正确编写了所有内容,但是,我没有收到错误堆栈。事实上,我根本没有通过数据库/核心数据获得反馈。我非常仔细地查看了我发布的代码,但我不明白为什么它不起作用。那么我的问题是:为什么它不起作用?

以上是关于核心数据到 SQL 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

核心数据 NSManagedObject 到 JSON 编码不起作用

核心数据 - 轻量级迁移不起作用

Asp.Net 核心临时数据和重定向操作不起作用

从核心数据中删除记录不起作用?

删除核心数据条目不起作用

核心数据 NSPredicate 不起作用[重复]