2015-10-29 55 views
3

我正在与NSInvocation一起工作,需要从中检索其中一个属性。为什么缓冲区需要在NSInvocation上__unsafe_unretained - getArgument:atIndex:?

我用下面的代码,但我有一些怪异的行为叫[invocation invoke];

NSString *propertyName = nil; 
[invocation getArgument:&propertyName atIndex:3]; 

我看,为了使ARC下工作,我们需要使用__unsafe_unretained

__unsafe_unretained NSString *propertyName = nil; 
[invocation getArgument:&propertyName atIndex:3]; 

它的工作,很好!但我想明白为什么。任何人都可以解释吗?

+2

这是一个dup或理解答案的好地方:http://stackoverflow.com/questions/8672675/why-does-the-arc-migrator-say-that-nsinvocations-setargument-is-没有安全,unle。关键是调用不保留参数。通过将其定义为不安全,您承认自己明白这一点,并且您将采取措施确保参数的生命周期> =调用 – danh

回答

3

signature-[NSInvocation getArgument:atIndex:]

- (void)getArgument:(void *)buffer 
     atIndex:(NSInteger)index 

所以buffer是类型化并不一定是对象。 ARC要求您使用非保留的参考(因此部分不保留参考对象),因为它不会保持参考对象的存在并且可能会悬垂(因此危险或不安全),因此必须将其作为qualified作为__unsafe_unretained,另请参见clang specification,你必须告诉ARC不要关心这块内存。

不再推荐使用NSInvocation,它不适用于ARC,并且在Swift中不可用。作为替代方案,您可以使用-[NSObject methodForSelector:]

+0

基本上,您可以传递任何内容,包括不支持'保留“和”释放“。这意味着对象必须作为一个简单的赋值来传递,因此'__unsafe_unretained'。 – Sulthan

+0

“无类型,不一定是对象” - >“任何东西,包括不支持保留和释放的类型”。 这里的问题是参考*有一个对象类型,所以你必须告诉ARC不要关心它。 – eik

0

问题是,谁负责修改对象的保留计数(如果它甚至是对象)。我认为它也被称为所有者。

我们可以试着说任何做这项任务的人应该是。但NSInvocation缺乏这方面的知识。它不知道你是否通过了__strong或__weak,并且不需要。这意味着在分配值时,调用不知道是否实际保留对象,因为它不知道对象是否会被释放。然后,该责任被发送给呼叫者。

而且,我想说,内存管理应该总是由调用者管理。例如,我们假设NSError的不同之处在于NSError可以被调用的函数分配,这就是为什么参数需要是__autorelease。 NSInvocation并非如此。

相关问题