怀疑__bridge,_bridge_retain和_bridge_transfer

时间:2015-05-25 18:10:03

标签: ios objective-c memory types casting

我已阅读有关__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设置为nil后,ARC将介入并取消分配字符串。因此释放了该部分内存,但cfString仍然指向那里,导致指针访问异常。与我的推理相反,输出为123且为null,当然程序不会崩溃。

此外,如果我更换

self.test = nil;

CFRelease(cfString);

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

任何人都可以详细说明原因吗?顺便说一句,所有权一词总是让我烦恼,一些解释将不胜感激。

2 个答案:

答案 0 :(得分:2)

您的问题是您使用的是常量字符串。这被直接放入程序存储器中,因此尽管不应该引用,但引用仍然意外地保持有效。使用比常量字符串更不变的东西,你的程序会像你想象的那样制动。

答案 1 :(得分:1)

问题是您的示例基于文字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;
}

如您所见,发布它们是不可能的。