【问题标题】:Cocoa Core Data: Setting default entity property values?Cocoa Core Data:设置默认实体属性值?
【发布时间】:2010-09-16 18:49:23
【问题描述】:

我知道我可以在数据模型或实体类的 -awakeFromInsert 方法中设置默认值。例如,要使“日期”属性默认为当前日期:

- (void) awakeFromInsert
{
NSDate *now = [NSDate date];
self.date = now;
}

如何将“idNumber”属性默认设置为比前一个对象的 idNumber 大一?

谢谢,奥利

编辑:我尝试的相关代码(现已更正)

- (void) awakeFromInsert
{
self.idNumber = [NSNumber numberWithInt:[self maxIdNumber] + 1];
}

-(int)maxIdNumber{
NSManagedObjectContext *moc = [self managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Flight" inManagedObjectContext:moc];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];

// Set example predicate and sort orderings...
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"idNumber > %@", [NSNumber numberWithInt:0]];
[request setPredicate:predicate];

[request setFetchLimit:1];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"idNumber" ascending:NO];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];

NSError *error;
NSArray *array = [moc executeFetchRequest:request error:&error];
if (array == nil | array.count == 0)
{
    return 0;
} 
return [[[array objectAtIndex:0] valueForKey:@"idNumber"] intValue];
}

如果调用 maxIdNumber 方法,新对象会被添加到表中两次!? (但使用正确的 idNumber)。表中的两个条目是链接的 - 编辑/删除一个也编辑/删除另一个。出于这个原因,我相信它与托管对象上下文有关。对于它的价值,无论在 awakFromNib 中调用多少次 maxIdNumber 方法,结果(两个副本)都是相同的;即使 self.idNumber 只是设置为 [NSNumber numberWithInt:5] 并且 maxIdNumber 方法只是为一次性变量调用。

有什么线索吗??

【问题讨论】:

  • 顺便说一句,Apple 不建议在实体中使用您自己的 ID 值。您可以使用 NSManagedObject 的 objectID 方法来获取 NSManagedObjectID 对象,它对于任何对象都是唯一的。
  • 不幸的是,当它被持久化到商店时,这个 id 会从临时 id 变为永久 id。可以理解的是,大多数开发人员只是为了简单起见而使用自己的 ID 系统,而且效果很好。
  • 谢谢,“idNumber”字段不是用于区分对象,它是用户必须提供的实体的属性(他们可以选择拥有两个具有相同 idNumber 的对象,有选择!!) .它将与实体的其他属性一起显示在表格中。

标签: cocoa core-data default-value


【解决方案1】:

解决了!

好的,当从 awakeFromInsert 方法中执行 fetch 请求时会出现双重输入的问题。引用自docs

通常不鼓励您在 awakeFromInsert 的实现中执行提取。虽然是允许的,但是执行 fetch 请求可能会触发内部 Core Data 通知的发送,这可能会产生不必要的副作用。例如,在 Mac OS X 上,一个 NSArrayController 的实例最终可能会在其内容数组中插入一个新对象两次。

一种解决方法是使用此处概述的 perfromSelector:withObject:afterDelay 方法(我只允许发布一个超链接:( ):http://www.cocoabuilder.com/archive/cocoa/232606-auto-incrementing-integer-attribute-in-awakefrominsert.html

我的工作代码现在如下:(注意,我已将上面使用的大部分获取代码放入一个类别中以稍微整理一下,这允许我使用方法 fetchObjectsForEntityName:withPredicate:withFetchLimit :withSortDescriptors:)

- (void) awakeFromInsert
{
[self performSelector:@selector(setIdNumber) withObject:nil afterDelay:0];
self.date = [NSDate date];
}


-(void)setIdNumber
{
int num  = 0;

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"idNumber" ascending:NO];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"idNumber > %@", [NSNumber numberWithInt:0]];

NSArray *array = [[self managedObjectContext] fetchObjectsForEntityName:@"Flight" 
                                                          withPredicate:predicate 
                                                         withFetchLimit:0
                                                    withSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];   

if (array != nil & array.count != 0)
{
    num = [[[array objectAtIndex:0] valueForKey:@"idNumber"] intValue]; 
} 

num ++;

[self setIdNumber:[NSNumber numberWithInt:num]];
}

让我知道你的想法!

【讨论】:

  • 如果这是答案,请点击复选标记,以便系统将其显示为已回答。
  • 我不能,我必须等到明天才能接受我自己的答案:( !!
【解决方案2】:

一种方法:为您的实体的所有实例创建一个提取请求,限制为 1,按 idNumber 排序以获得最高数字。

另一种方法:在商店的元数据中保留最高的 idNumber 并不断增加它。

有很多支持和反对的论据。归根结底,这两个是最常见的,您可以自行选择。

【讨论】:

  • 感谢您的回复。好的,所以我设法创建了一个返回最高 idNumber 的获取请求,太棒了!但是,每当我使用此代码设置 idNumber 属性时,该对象都会两次添加到表中!?!?! (尽管删除两个实例中的任何一个,使用删除按钮都会删除两者)。有什么想法吗?
  • 你去吧,我把它放在原来的帖子里,让它更清晰。
  • 看起来您没有显示 -maxIDNumber 的使用方式。
  • 对不起。好的,所有相关信息现在都应该在原始帖子中。此外,获取请求的代码相当冗长,我计划将其移至一个类别,以提供一个更简洁的方法,类似于“fetchObjectsForEntityName:withPredicate:withFetchLimit:withSortDescriptors:”。坏主意,好主意?
  • 当你返回一个 int 时,为什么你的返回类型是 NSNumber?一开始我没听懂。
【解决方案3】:

一个更简单的方法是重写 NSArrayController 的 newObject 方法:

- (id) newObject
{
    id result=[super newObject];
    [result setValue: [NSDate date] forKey: @"date"];
    return result;
}

【讨论】:

    猜你喜欢
    • 2011-03-07
    • 1970-01-01
    • 2013-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多