我的测试代码:
NSManagedObjectContext *context;
.....
NSAutoreleasePool *pool = [NSAutoreleasePool new];
User *u = (User *)[NSEntityDescription insertNewObjectForEntityForName:@"User" inManagedObjectContext:context];
NSLog(@"after create:%d", [u retainCount]);
[context deleteObject:u];
NSLog(@"after delete:%d", [u retainCount]);
[context save:NULL];
NSLog(@"after save:%d", [u retainCount]);
[pool drain];
[pool release];
NSLog(@"after pool release:%d", [u retainCount]);
[u release];
NSLog(@"after user release:%d", [u retainCount]);
u.loginName = @"aaaa";
结果:
2010-08-13 10:04:54.558 BriefCase[7448:207] after create:2
2010-08-13 10:04:54.560 BriefCase[7448:207] after delete:3
2010-08-13 10:04:54.561 BriefCase[7448:207] after save:1
2010-08-13 10:04:54.562 BriefCase[7448:207] after pool release:1
2010-08-13 10:04:54.563 BriefCase[7448:207] after user release:0
Program received signal: “EXC_BAD_ACCESS”.
根据Core Data文档,insertNewObjectForEntityForName:inManagedObjectContext:将返回一个自动释放的对象。因此,在删除,保存和释放池之后,应该释放对象u。我明白错了什么?
另一个问题,在[u release]之后,为什么[u retainCount]可以返回0,我认为它应该是“EXC_BAD_ACCESS”。
答案 0 :(得分:5)
核心数据拥有它,你没有。如果您想获得所有权,请保留它。但是,仅仅因为你不拥有它并不能保证它会在下一次自动释放池的释放时被释放。核心数据可能决定在未使用的时间段内挂起它。
简短回答:遵循保留/释放规则,将Core Data的内存管理保留到Core Data。它在幕后做了很多事情。
此外,您无需投射id
。与核心数据和整个Objective-C中的大多数方法一样,-insertNewObjectForEntityForName: inManagedObjectContext:
返回id
。 id
永远不需要被投射。转换只是骗代编译器,可能会引入微妙的错误。
最后,你永远不应该关注或依赖-retainCount
。仅仅因为你发布它并不意味着基金会的某些部分仍然没有引用它。 -retainCount
没有价值。
id
没有编译器警告,因为它不是警告。返回id
表示它是一个通用对象,可以将其分配给任何东西。实际上,您可以将其保留为id
,并且仍然可以在世界上调用任何方法。当然,如果该方法在运行时不存在,那么您将获得异常。它是Objective-C基础知识及其动态特性的一部分。对学习至关重要的东西。
User *u = [NSEntityDescription insertNewObjectForEntityForName:@"User" inManagedObjectContext:context];
是否正确处理。与Java和C#不同; Objective-C不是强制转换语言,因为您发送的是消息而不是调用方法,所以这些调用在运行时解析,因此无论如何您都声称对象是无关紧要的。声称它是User
是有帮助的,这样你就可以进行一些编译时间检查,但是如果你尝试在它上面调用-thisMethodDoesNotExist
,你只需要编译警告。该消息仍将尝试在运行时发送,然后才会出现异常。这是Objective-C的基本和重要部分。
-retainCount
-retainCount
不可靠,永远不应该使用。你从中得到的东西可能毫无意义。
此外,您正在使用Core Data并针对Core Data对象对其进行测试,这使事情变得更糟。即使您处于单个线程中,也无法保证(实际上不太可能)Core Data仅在内部使用单个线程。这是-retainCount
不应该使用的众多原因之一。它不够透明,即使在测试中依赖它也是一个坏主意。