需要更多关于__autoreleasing的使用的解释

 mobiledu2502855757 发布于 2023-02-06 12:08

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

在哪些情况下我们需要在ARC下编写__autoreleasing所有权限定符?

在代码段示例中使用__autoreleasing

NSError和__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它什么都不改变?这是我不明白的.谁能告诉我我错过了什么?感谢大家

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

    想象一下你的方法如下:

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

    编译器认为这*error很强,所以当它完成赋值时,你得到+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];
    }
    

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

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

    2023-02-06 12:10 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有