保存managedObjectContext时出现奇怪的崩溃

时间:2010-08-25 18:46:11

标签: iphone cocoa-touch core-data video model

当我尝试保存模型时,我遇到了一个奇怪的崩溃。这是我的代码:

 TJModel *model = [TJModel sharedTJModel];
 NSFetchRequest *request = [[[NSFetchRequest alloc] init]autorelease];
 [request setReturnsObjectsAsFaults:NO];
 NSEntityDescription *entity = [NSEntityDescription entityForName:@"TJVideoList"inManagedObjectContext:[model managedObjectContext]];
 [request setEntity:entity];

 NSError *error = nil;
 NSMutableArray *mutableFetchResults = [[[model managedObjectContext] executeFetchRequest:request error:&error] mutableCopy];

if (error != nil)
  NSLog(@"error %@",[error localizedDescription]);


 TJVideoList *videoList = nil;

 if ([mutableFetchResults count] == 0) {

  videoList = (VideoList *)[NSEntityDescription insertNewObjectForEntityForName:@"TJVideoList" 
                 inManagedObjectContext:[model managedObjectContext]];
 }
 else 
 {
  videoList = [mutableFetchResults objectAtIndex:0];
 }


 [videoList addVideoListObject:recordedVideo];
 error = nil;

 if (![[model managedObjectContext] save:&error]) {

然后崩溃.....这就是终端里说的话:

-[NSConcreteValue UTF8String]: unrecognized selector sent to instance 0x1d33f0

我认为这可能是解除分配对象的一个​​问题,所以我保留了它们:

[managedObjectContext setRetainsRegisteredObjects:YES];

没有运气。

2 个答案:

答案 0 :(得分:1)

听起来更像是你分配了一个NSValue实例(NSNumber,很可能,因为它是最常用的子类),其中需要NSString。 -retainsRegisteredObjects:不太可能需要(无论如何都不会修复与内存相关的问题)。

它也可能是一个过度释放的问题。尝试在启用Zombie检测的情况下运行(请参阅“运行”菜单)。

答案 1 :(得分:1)

您的崩溃不是此代码的结果。

保存中的崩溃通常是由managedObject属性的错误引起的。在这种情况下,您在某处为字符串属性分配了错误的值。当上下文将字符串属性转换为UTF8字符串以进行持久化时,那里的对象而不是NSString不理解消息和崩溃结果。

虽然这段代码应该运行正常,但你确实有一些冒险的做法:

NSFetchRequest *request = [[[NSFetchRequest alloc] init]autorelease];

这是一种不好的做法。 autorelease与发布相同。在完成操作之前,不应将其发送给对象。 autorelease标记下次内存池耗尽时的死亡对象。在某些情况下,这会意外地杀死对象。虽然它不会在这里引起问题,但你不想养成这种捷径的习惯,因为它最终会咬你。

当对象使用当前作用域但对象是在作用域外发送时(通常在方法返回中),您应该只使用自动释放。

NSMutableArray *mutableFetchResults = [[[model managedObjectContext] executeFetchRequest:request error:&error] mutableCopy];

这里的可变数组与副本一样毫无意义。这显然是某些参考资料,因为它在过去几个月里不断出现新手代码。如果您不打算更改数组,则没有理由让它变得可变。对于托管对象数组,复制数组毫无意义。

videoList = [mutableFetchResults objectAtIndex:0]

由于fetch没有排序描述符,mutableFetchResults数组将以随机顺序排列。如果您返回了多个对象(几乎总是如此),则每次运行代码时,您将在零元素处获得一个随机TJVideoList对象。