我正在尝试将数据插入到coredata中,但我收到错误,
CoreData:错误:(1555)UNIQUE约束失败:ZSIDETABLENAME.Z_PK
情景: -
首先:从appdelegate.m我将数据从我的SQL文件复制到文档目录的sql文件。
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
// Create the coordinator and store
NSString* from;
NSString* to;
NSArray* mainPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [mainPath objectAtIndex:0]; // Get documents folder
/*VoiceRecords.plist file*/
from=[[NSBundle mainBundle]pathForResource:@"News" ofType:@"sqlite"];
to=[documentsDirectory stringByAppendingPathComponent:@"News.sqlite"];
[[NSFileManager defaultManager]copyItemAtPath:from
toPath:to error:nil];
from=nil;
to=nil;
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"News.sqlite"];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&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.
Typical reasons for an error here include:
* The persistent store is not accessible;
* The schema for the persistent store is incompatible with current managed object model.
Check the error message to determine what the actual problem was.
If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.
If you encounter schema incompatibility errors during development, you can reduce their frequency by:
* Simply deleting the existing store:
[[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;
}
它正常工作。然后我试图保存用户在mainviewcontroller.m中的coredata中输入的URL。
- (void)feedParserDidFinish:(MWFeedParser *)parser {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"IWorld"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"feedurl = %@", self.Feedlink];
NSManagedObjectContext *context = [self managedObjectContext];
if ([[context executeFetchRequest:fetchRequest error:NULL] count] == 0) {
NSError *error = nil;
NSPredicate *predicate=[NSPredicate predicateWithFormat:@"feedurl contains %@",check];
[fetchRequest setPredicate:predicate];
NSMutableArray *checkp = [[context executeFetchRequest:fetchRequest error:&error]mutableCopy];
if (checkp.count<=0) {
NSManagedObject *newDevice = [NSEntityDescription insertNewObjectForEntityForName:@"IWorld" inManagedObjectContext:context];
[newDevice setValue:self.Name forKey:@"name"];
[newDevice setValue:self.WebsiteName forKey:@"websitename"];
[newDevice setValue:self.Feedlink forKey:@"feedurl"];
// Save the object to persistent store
if (![context save:&error]) {
NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]);
}
//Save value in lockbox
NSArray *keys = [[[newDevice entity] attributesByName] allKeys];
NSDictionary *dict = [newDevice dictionaryWithValuesForKeys:keys];
}
}
NSFetchRequest *fetchrequestforside=[NSFetchRequest fetchRequestWithEntityName:@"Sidetablename"]; //Sidetablename is entity
fetchrequestforside.predicate=[NSPredicate predicateWithFormat:@"feedurl = %@", self.Feedlink];
NSManagedObjectContext *context = [self managedObjectContext];
if ([[context executeFetchRequest:fetchrequestforside error:NULL] count] == 0) {
// Create a new managed object
NSError *error = nil;
NSPredicate *predicate=[NSPredicate predicateWithFormat:@"feedurl contains %@",check ]; //check is urlstring
[fetchrequestforside setPredicate:predicate];
NSMutableArray *checkp = [[context executeFetchRequest:fetchrequestforside error:&error]mutableCopy];
if (checkp.count<=0) //if coredata will find url then notstore in coredata else stored procedure
{
NSManagedObject *newDevice1 = [NSEntityDescription insertNewObjectForEntityForName:@"Sidetablename" inManagedObjectContext:context];
if (self.Name)
{
[newDevice1 setValue:self.Name forKey:@"name"];
}
if (self.WebsiteName)
{
[newDevice1 setValue:self.WebsiteName forKey:@"websitename"];
}
if (self.Feedlink)
{
[newDevice1 setValue:self.Feedlink forKey:@"feedurl"];
}
NSError *error = nil;
if (![context save:&error]) {
NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]); // Getting error here through nslog //CoreData: error: (1555) UNIQUE constraint failed: ZSIDETABLENAME.Z_PK
}
注意:这一切都是在第一时间发生的。第二次我将运行应用程序所有工作正常。不知道问题出在哪里?
答案 0 :(得分:3)
您在sidetablename表上遇到主键约束违规。
因此,我认为您的问题在于如何创建和复制种子数据库。
很遗憾,您没有提供该信息。因此,我只是猜测你是如何做到的。
我假设您使用mac app创建了数据库,或者您是在iOS模拟器中创建的。然后,您将sqlite文件从创建的任何位置复制到捆绑包资源中。
由于WAL自iOS / OSX 7 / 10.9以来一直是默认模式,我假设您在WAL模式下创建了种子数据库。这意味着您可能错过了-wal和-shm文件。如果您指定任何数据属性应使用外部存储,那么您也错过了这些数据。
创建要复制的种子数据库时,还需要复制-shm / wal文件,或者需要以回滚日志模式创建数据库,该模式将在文件中添加所有数据。
您可以通过在添加持久性存储时设置以下选项来实现此目的(如果您已经使用了选项,只需将其与其他选项合并)。
NSDictionary *options = @{NSSQLitePragmasOption:@{@"journal_mode":@"DELETE"}};
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:options
error:&error]) {
// Handle error
}
这是在创建要复制到捆绑包的数据库时添加持久性存储的方法。它将确保所有内容都在实际的数据库文件中。
现在,在运行代码来创建种子文件之后,您应该转到该目录并查看是否存在任何其他文件。最好的方法是在终端。转到该目录并执行&#34; ls -lat&#34;它将列出按时间排序的所有文件。
警告:SQLite和Core Data都可以创建与sqlite文件一起使用的额外文件,具体取决于两个实体的配置。因此,您通常应将每个核心数据持久性存储视为文件包。换句话说,您应该为核心数据存储创建一个单独的目录。这样,当SQLite或核心数据决定创建额外文件时,所有内容都被限制在一个目录中。
当您将文件复制到捆绑资源时,从您创建种子数据库的位置,您需要确保复制所有内容。
同样,您应该在部署时将所有内容从捆绑包复制到设备。
但是,您应该在NSPersistentStoreCoordinator
...
/* Used for save as - performance may vary depending on the type of old and
new store; the old store is usually removed from the coordinator by the
migration operation, and therefore is no longer a useful reference after
invoking this method
*/
- (NSPersistentStore *)migratePersistentStore:(NSPersistentStore *)store
toURL:(NSURL *)URL
options:(nullable NSDictionary *)options
withType:(NSString *)storeType
error:(NSError **)error;
/* copy or overwrite the target persistent store in accordance with the store
class's requirements. It is important to pass similar options as
addPersistentStoreWithType: ... SQLite stores will honor file locks, journal
files, journaling modes, and other intricacies. Other stores will default
to using NSFileManager.
*/
- (BOOL)replacePersistentStoreAtURL:(NSURL *)destinationURL
destinationOptions:(nullable NSDictionary *)destinationOptions
withPersistentStoreFromURL:(NSURL *)sourceURL
sourceOptions:(nullable NSDictionary *)sourceOptions
storeType:(NSString *)storeType
error:(NSError**)error NS_AVAILABLE(10_11, 9_0);
因此,我相信如果您正确创建数据库,然后将其完全正确地复制到资源包和应用程序中,那么您的问题就会消失。
答案 1 :(得分:0)
当我在后台线程上创建/更新coredata实体时,在主线程上执行相同操作解决了该问题。