关于__bridge、_bridge_retain和_bridge_transfer的疑问

Doubts about __bridge, _bridge_retain and _bridge_transfer

我阅读了 __bridge_bridge_retain_bridge_transfer 并做了一些实验。但是输出与我的预期不一致。特别是,我有以下代码:

@interface ViewController ()
@property (nonatomic, strong) NSString *test;
@end

@implementation ViewController

CFStringRef cfString;

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.test = @"123";
    cfString = (__bridge CFStringRef)self.test;
    self.test = nil;    
}

- (void)viewDidAppear:(BOOL)animated
{
    NSLog(@"%@", cfString);
    NSLog(@"%@", self.test);
}

我预计程序会崩溃,基于以下推理:_bridge 不转移所有权,因此在将 self.test 转换为 cfString 时,没有 retainCount 增量。一旦 self.test 设置为 nilARC 将介入并释放字符串。所以那部分内存被释放了,但是 cfString 仍然指向那里,导致指针错误访问异常。与我的推理相反,输出是123和null,程序当然不会崩溃。

此外,如果我更换

self.test = nil;

CFRelease(cfString);

由于类似的原因,我预计程序也会崩溃。更奇怪的是现在输出是123和123.

谁能详细说说为什么?顺便说一句,所有权这个词总是困扰着我,一些解释将不胜感激。

您的问题是您使用的是常量字符串。这是直接放入程序内存中的,因此该引用出人意料地保持有效,尽管它不应该如此。使用比常量字符串更不常量的东西,你的程序就会像你想象的那样刹车。

问题是您的示例基于文字 NSString 值。

在objective-C中,常量NSString(编译时已知的常量值)永远不会被释放。事实上,他们主要的内存管理方法是这样的:

+ (id)allocWithZone:(NSZone *)zone {
    id _uniqueInstance = [self _singletonInstanceOfClass];

    if( _uniqueInstance == nil )
        _uniqueInstance = [super allocWithZone:zone];

    return _uniqueInstance;
}

- (id)copyWithZone:(NSZone *)zone {
    (void)zone;
    return self;
}

- (id)retain {
    return self;
}

- (NSUInteger)retainCount {
    return NSUIntegerMax;  // denotes an object that cannot be released
}

- (oneway void)release {
    //do nothing
    return;
}

- (id)autorelease {
    return self;
}

如您所见,无法释放它们。