我在理解Core Data方面遇到了一些困难。如何创建一个具有唯一ID的新条目? 在SQL中,我只需将一个字段声明为自动递增字段即可。但我在这里没有看到类似的东西,但我可能只是漏看了什么。我只想要一个自动递增的NSInteger字段,因此当我手动向数据库添加项目时,我将拥有某种参考。
我在理解Core Data方面遇到了一些困难。如何创建一个具有唯一ID的新条目? 在SQL中,我只需将一个字段声明为自动递增字段即可。但我在这里没有看到类似的东西,但我可能只是漏看了什么。我只想要一个自动递增的NSInteger字段,因此当我手动向数据库添加项目时,我将拥有某种参考。
虽然我同意你的观点,但在Core Data背后存在一种ID机制。ID确实由Core Data管理,但可以使用以下方式检索它们:
NSManagedObjectID *moID = [managedObject objectID];
更多信息请参见: Core Data编程指南
这不是CoreData的工作方式。
在CoreData中,你创建实体的实例。每个实例都是独特的。然后根据需要检索和操作实例。CoreData会为你处理持久性,包括唯一标识实例。
远离你所知道的传统关系型数据库的一切。
CoreData是一个非常强大的技术,提供了远超过仅仅数据库持久化的功能。如果你采用它,它可以节省你很多代码并且表现出色。
这个类函数将为您的id属性(必须是整数属性)返回下一个可用数字。
我称它为自动递增值生成器。我仍然同意其他人的看法,即可以使用objectID,但有时您只需要数字。
您可以将此函数放在实体的NSManagedObject子类中:
+(NSNumber *)nextAvailble:(NSString *)idKey forEntityName:(NSString *)entityName inContext:(NSManagedObjectContext *)context{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSManagedObjectContext *moc = context;
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:moc];
[request setEntity:entity];
// [request setFetchLimit:1];
NSArray *propertiesArray = [[NSArray alloc] initWithObjects:idKey, nil];
[request setPropertiesToFetch:propertiesArray];
[propertiesArray release], propertiesArray = nil;
NSSortDescriptor *indexSort = [[NSSortDescriptor alloc] initWithKey:idKey ascending:YES];
NSArray *array = [[NSArray alloc] initWithObjects:indexSort, nil];
[request setSortDescriptors:array];
[array release], array = nil;
[indexSort release], indexSort = nil;
NSError *error = nil;
NSArray *results = [moc executeFetchRequest:request error:&error];
// NSSLog(@"Autoincrement fetch results: %@", results);
NSManagedObject *maxIndexedObject = [results lastObject];
[request release], request = nil;
if (error) {
NSLog(@"Error fetching index: %@\n%@", [error localizedDescription], [error userInfo]);
}
//NSAssert3(error == nil, @"Error fetching index: %@\n%@", [error localizedDescription], [error userInfo]);
NSInteger myIndex = 1;
if (maxIndexedObject) {
myIndex = [[maxIndexedObject valueForKey:idKey] integerValue] + 1;
}
return [NSNumber numberWithInteger:myIndex];
}
Swift 5.0
func nextAvailble(_ idKey: String, forEntityName entityName: String, in context: NSManagedObjectContext) -> NSNumber? {
let req = NSFetchRequest<NSFetchRequestResult>.init(entityName: entityName)
let entity = NSEntityDescription.entity(forEntityName: entityName, in: context)
req.entity = entity
req.fetchLimit = 1
req.propertiesToFetch = [idKey]
let indexSort = NSSortDescriptor.init(key: idKey, ascending: false)
req.sortDescriptors = [indexSort]
do {
let fetchedData = try context.fetch(req)
let firstObject = fetchedData.first as! NSManagedObject
if let foundValue = firstObject.value(forKey: idKey) as? NSNumber {
return NSNumber.init(value: foundValue.intValue + 1)
}
} catch {
print(error)
}
return nil
}
NSSortDescriptor *indexSort = [[NSSortDescriptor alloc] initWithKey:idKey ascending:NO];
然后取消注释 request.fetchLimit = 1;
。 - Jason Moore以下是CoreData对象的三种唯一ID表示方式:
NSManagedObjectID *taskID = [task objectID];
NSURL *taskUniqueURLKey = task.objectID.URIRepresentation;
NSString *taskUniqueStringKey = task.objectID.URIRepresentation.absoluteString;
注意:如果您想将上述唯一键用作索引,请确保在使用它之前将对象保存到上下文中,否则对象ID将是临时ID,稍后将被替换(例如,在保存后)。有关NSManagedObjectID类的详细信息,请参阅苹果文档:
- (BOOL)isTemporaryID; // indicates whether or not this ID will be replaced later,
such as after a save operation (temporary IDs are assigned to newly inserted objects
and replaced with permanent IDs when an object is written to a persistent store); most
IDs return NO
核心数据用于持久性框架,该框架抽象了主键。
每个NSManagedObject都有自己的内置唯一键,在其objectID属性中可用。
此id在内部用于链接实体的关系。无需像在SQL中所做的那样维护自己的id作为主键。
您始终可以通过NSManagedObject.objectID获取id,并使用NSMananagedObjectContext.objectWithId获取对象上下文
更新@Lukasz在Swift中的答案:
static func nextAvailble(_ idKey: String, forEntityName entityName: String, inContext context: NSManagedObjectContext) -> Int {
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: entityName)
fetchRequest.propertiesToFetch = [idKey]
fetchRequest.sortDescriptors = [NSSortDescriptor(key: idKey, ascending: true)]
do {
let results = try context.fetch(fetchRequest)
let lastObject = (results as! [NSManagedObject]).last
guard lastObject != nil else {
return 1
}
return lastObject?.value(forKey: idKey) as! Int + 1
} catch let error as NSError {
//handle error
}
return 1
}