Ros*_*ari 6 xcode objective-c nsobject ios automatic-ref-counting
根据ARCin iOS,一个对象必须至少有一个strong引用留在内存中,当没有strong引用时(即引用计数变为0),该对象将从内存中释放,我们将不再访问该对象.
但我的代码中出现了奇怪的行为.
我在代码中分配weak引用NSString,当我写[[NSString alloc] init]; Xcode时发出警告.
__weak NSString *str;
str = [[NSString alloc] init];
Run Code Online (Sandbox Code Playgroud)
将保留对象分配给弱属性; 对象将在分配后释放.

如果我这样做,Xcode不会发出任何警告,
__weak NSString *str;
str = @"abcd";
NSLog(@"%@",str);
Run Code Online (Sandbox Code Playgroud)

输出:abcd

我的问题是
为什么它打印"abcd"作为输出.即使str是弱参考变量.谁在保持这个NSString对象的值在内存中是"abcd"?
当您说str = @"abcd",您没有使用编译器识别为返回新分配的对象的代码模式,因此您不会触发有关将新对象直接分配给__weak变量的警告.
此外,字符串文字@"abcd"存储在程序的可执行文件中.它永远不会被解除分配.在retain和release操作实际上并不改变其保留计数.其保留计数设置为表示不朽对象的幻数.因此,您的__weak变量str实际上并未设置为nil,因为它引用的对象不会被释放.这就是它打印的原因abcd.
事实上,如果你指定一个字符串文字(而不是像数组文字这样的其他文字@[a, b, c]),clang会特别禁止警告.请参阅clang源代码中的注释:
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;
}
Run Code Online (Sandbox Code Playgroud)
因此,如果我们将类型更改为NSArray并使用数组文字,我们会收到警告:
继续......当你说str = [[NSString alloc] init]因为编译器识别[[NSString alloc] init]出通常返回一个新对象的代码模式时,你会收到警告.
但是,在特定情况下[[NSString alloc] init],您会发现str再次没有设置为nil.那是因为-[NSString init]特殊情况下返回一个全局空字符串对象.它实际上并不会在每次调用时创建一个新对象.
__weak NSString *str;
str = [[NSString alloc] init];
NSLog(@"%ld %p [%@]", CFGetRetainCount((__bridge CFTypeRef)str), str, str);
Run Code Online (Sandbox Code Playgroud)
输出:
2018-01-24 01:00:22.963109-0600 test[3668:166594] 1152921504606846975 0x7fffe55b19c0 []
Run Code Online (Sandbox Code Playgroud)
1152921504606846975是魔术保留计数,表示不朽的物体.
| 归档时间: |
|
| 查看次数: |
662 次 |
| 最近记录: |