谁拥有对象返回insertNewObjectForEntityForName:inManagedObjectContext:

gwa*_*ang 1 iphone core-data

我的测试代码:

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";
Run Code Online (Sandbox Code Playgroud)

结果:

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”.
Run Code Online (Sandbox Code Playgroud)

根据Core Data文档,insertNewObjectForEntityForName:inManagedObjectContext:将返回一个自动释放的对象.因此,在删除,保存和释放池之后,应该释放对象u.我明白错了什么?

另一个问题,在[u release]之后,为什么[u retainCount]可以返回0,我认为它应该是"EXC_BAD_ACCESS".

Mar*_*rra 5

核心数据拥有它,你没有.如果您想获得所有权,请保留它.但是,仅仅因为你不拥有它并不能保证它会在下一次自动释放池的释放时被释放.核心数据可能决定在您使用之外的未知时间段内挂起它.

简短回答:遵循保留/释放规则,将Core Data的内存管理保留到Core Data.它在幕后做了很多事情.

此外,你不需要施放id. -insertNewObjectForEntityForName: inManagedObjectContext:与Core Data中的大多数方法和整个Objective-C一样,返回id. id永远不需要演员.转换只是骗代编译器,可能会引入微妙的错误.

最后,你永远不应该关注或依赖-retainCount.仅仅因为你发布它并不意味着基金会的某些部分仍然没有引用它. -retainCount没有价值.

回归 id

没有编译器警告,因为它不是警告.返回id意味着它是一个通用对象,它可以分配给任何东西.事实上,你可以将它作为一个id并且仍然在世界上调用任何方法.当然,如果该方法在运行时不存在,那么您将获得异常.它是Objective-C基础知识及其动态特性的一部分.对学习至关重要的东西.

User *u = [NSEntityDescription insertNewObjectForEntityForName:@"User" inManagedObjectContext:context];
Run Code Online (Sandbox Code Playgroud)

是正确的处理.与Java和C#不同; Objective-C不是强制转换语言,因为您发送消息而不是调用方法,所以这些调用在运行时被解析,因此无论如何您都声称对象是无关紧要的.声称它是一个有用的User,你可以得到一些编译时检查,但如果你尝试调用-thisMethodDoesNotExist它,你将只编译一个警告.该消息仍将尝试在运行时发送,然后才会出现异常.这是Objective-C的基础和重要部分.

-retainCount

-retainCount是不可靠的,永远不应该使用.你从中得到的回报可能毫无意义.

此外,您正在使用Core Data并针对Core Data对象对其进行测试,这使事情变得更糟.即使您处于单个线程中,也无法保证(实际上不太可能)Core Data仅在内部使用单个线程.这是-retainCount不应该使用的众多原因之一.它不够透明,即使在测试中依赖它也是一个坏主意.