核心数据到 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 不起作用的主要内容,如果未能解决你的问题,请参考以下文章