当我尝试保存模型时,我遇到了一个奇怪的崩溃。这是我的代码:
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];
没有运气。
答案 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
对象。