关于__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
设置为 nil
,ARC
将介入并释放字符串。所以那部分内存被释放了,但是 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;
}
如您所见,无法释放它们。
我阅读了 __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.
谁能详细说说为什么?顺便说一句,所有权这个词总是困扰着我,一些解释将不胜感激。
您的问题是您使用的是常量字符串。这是直接放入程序内存中的,因此该引用出人意料地保持有效,尽管它不应该如此。使用比常量字符串更不常量的东西,你的程序就会像你想象的那样刹车。
问题是您的示例基于文字 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;
}
如您所见,无法释放它们。