gpt4 book ai didi

ios - 将对象分配给 Objective-C 中的弱引用?

转载 作者:可可西里 更新时间:2023-11-01 04:37:09 25 4
gpt4 key购买 nike

根据 iOS 中的 ARC ,一个对象必须至少有一个 strong 引用才能留在内存中,当没有 strong 引用(即引用计数变为 0),对象将从内存中释放,我们将无法再访问该对象。

但是我的代码出现了奇怪的行为。

我在代码中分配给 weak 引用 NSString,当我写 [[NSString alloc] init]; Xcode 时给出警告。

__weak NSString *str;
str = [[NSString alloc] init];

Assigning retained object to weak property; object will be released after assignment.

Xcode warning screenshot

如果我这样做,Xcode 不会给出任何警告,

__weak NSString *str;
str = @"abcd";
NSLog(@"%@", str);

No Warning Screenshot

输出:abcd

Output Screenshot

我的问题是:

为什么它打印 "abcd" 作为输出。即使 str 是一个 引用变量。谁在内存中保留这个值为 "abcd"NSString 对象?

最佳答案

当你说 str = @"abcd" 时,你没有使用编译器识别为返回新分配对象的代码模式,因此你不会触发有关 a 的警告将新对象直接分配给 __weak 变量。

此外,像@"abcd" 这样的字符串文字存储在程序的可执行文件中。它永远不会被释放。 retainrelease 操作实际上并没有改变它的保留计数。它的保留计数设置为一个表示不朽对象的魔数(Magic Number)。所以你的 __weak 变量 str 实际上并没有设置为 nil,因为它引用的对象没有被释放。这就是它打印 abcd 的原因。

事实上,如果您分配一个字符串文字(与数组文字 @[a, b, c] 等其他类型的文字相对),clang 会特别抑制警告。请参阅 the clang source code 中的评论:

static bool checkUnsafeAssignLiteral(Sema &S, SourceLocation Loc,
Expr *RHS, bool isProperty) {
// Check if RHS is an Objective-C object literal, which also can get
// immediately zapped in a weak reference. Note that we explicitly
// allow ObjCStringLiterals, since those are designed to never really die.
RHS = RHS->IgnoreParenImpCasts();

// This enum needs to match with the 'select' in
// warn_objc_arc_literal_assign (off-by-1).
Sema::ObjCLiteralKind Kind = S.CheckLiteralKind(RHS);
if (Kind == Sema::LK_String || Kind == Sema::LK_None)
return false;

S.Diag(Loc, diag::warn_arc_literal_assign)
<< (unsigned) Kind
<< (isProperty ? 0 : 1)
<< RHS->getSourceRange();

return true;
}

因此,如果我们将类型更改为 NSArray 并使用数组文字,我们会收到警告:

array literal assignment warning

继续......当你说 str = [[NSString alloc] init] 时你会收到警告,因为编译器识别出 [[NSString alloc] init] 是一个通常返回新对象的代码模式。

但是,在 [[NSString alloc] init] 的特殊情况下,您会发现 str 再次没有得到设置为零。那是因为 -[NSString init] 是特殊情况下返回一个全局空字符串对象。它实际上并没有在每次调用时创建一个新对象。

    __weak NSString *str;
str = [[NSString alloc] init];
NSLog(@"%ld %p [%@]", CFGetRetainCount((__bridge CFTypeRef)str), str, str);

输出:

2018-01-24 01:00:22.963109-0600 test[3668:166594] 1152921504606846975 0x7fffe55b19c0 []

1152921504606846975 是表示不朽对象的魔法保留计数。

关于ios - 将对象分配给 Objective-C 中的弱引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48416192/

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