gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-30 03:41:16 24 4
gpt4 key购买 nike

我拼命想了解 __autoreleasing 关键字在 Objective-C 中的用法。我已仔细阅读以下问题的答案:

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;
}

编译器认为 *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 声明为强错误或弱错误,并且编译器有机会对返回的引用做一些明智的事情。

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

关于objective-c - 需要更多关于 __autoreleasing 用法的解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20949886/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com