objective-c – 需要更多关于__autoreleasing使用的解释

我拼命想要了解Objective-C中__autoreleasing关键字的用法.我已经彻底阅读了以下问题的答案:

In which situations do we need to write the __autoreleasing ownership qualifier under ARC?

Use of __autoreleasing in code snippet example

NSError and __autoreleasing

尽管现在我明白我仍然无法得到主要的东西,目的.为什么这样?让我解释一下究竟让我困惑的是什么.考虑一下代码

@interface MyError : NSError

@end

@implementation MyError

- (void)dealloc
{
   NSLog(@"My error dealloc");
}

@end

@interface ErrorHandler : NSObject

- (void)handleError:(MyError* __strong*)error;

@end

@implementation ErrorHandler

- (void)handleError:(MyError* __strong*)error
{
   *error = [[MyError alloc] initWithDomain:@"Blabla" code:100500 userInfo:@{

                                                                          NSLocalizedDescriptionKey : @"TestDescription"


                                                                          }];
 }

 @end

 - (void)test
{
   MyError *error = nil;

   ErrorHandler *handler = [ErrorHandler new];

   [handler handleError:&error];

   NSLog(@"Localized description %@",error.localizedDescription);
}

我写了这段代码,看看如果我不使用__autoreleasing会发生什么.如您所见,handleError方法接受对显式声明为__strong的引用的引用.没有任何反应.一切都好.我能够从MyError对象获取信息并且已成功解除分配,我明白了.如果我把__autoreleasing而不是__strong没有任何改变.那么为什么使用__autoreleasing如果什么都没改变呢?这是我不明白的.谁能告诉我我错过了什么?感谢大家

解决方法

我认为tl; dr的答案是,通过将参数声明为__autoreleasing,如果你愿意,你也可以传递一个指向弱引用的指针.

想象一下你的方法如下:

-(void) handleError: (NSError* __strong *) error
{
    NSError* myError = [[NSError alloc] init];
    *error = myError; 
}

编译器认为*错误很强,因此当它执行赋值时,会得到1个保留计数.在编译器完成代码之后,它看起来像这样:

-(void) handleError: (NSError* __strong *) error
{
    NSError* myError = [[NSError alloc] init];
    *error = [myError retain]; 
    [myError release];
}

所以,如果你这样称呼它:

NSError* error; // strong reference
[self handleError: &error];

一切都很好,因为编译器会在范围的末尾正确地发布版本.如果你这样做:

NSError* __weak error; // weak reference
[self handleError: &error];

它可能不会编译,但如果确实如此,因为编译器认为引用很弱(它无法在handleError :)中看到强大的赋值,它将不会放入一个版本并且该对象将泄漏.

如果您定义这样的方法

-(void) handleError: (NSError* __weak *) error
{
    NSError* myError = [[NSError alloc] init];
    *error = myError; 
}

编译器添加代码,如下所示:

-(void) handleError: (NSError* __weak *) error
{
    NSError* myError = [[NSError alloc] init];
    *error = myError; 
    [myError release];
}

更糟糕的是因为* error的赋值给出0保留计数,这意味着,只要myError超出范围,即当方法返回时,它指向的对象就会被释放.

如果你这样做:

-(void) handleError: (NSError* __autoreleasing *) error
{
    NSError* myError = [[NSError alloc] init];
    *error = myError; 
}

编译器执行此操作:

-(void) handleError: (NSError* __autoreleasing *) error
{
    NSError* myError = [[NSError alloc] init];
    *error = [[myError retain] autorelease]; 
    [myError release];
}

与前一种情况相同,但返回的对象位于方法末尾的自动释放池中,因此不会取消分配.因此,您可以将调用者中的错误声明为强或弱,并且编译器有机会对返回的引用执行一些合理的操作.

至少我认为这就是问题所在.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...