core foundation也是支持ARC的,也有count的概念, 当一个实体的count(引用次数)为0的时候,系统就会回收这个实体的资源.
1.通过函数有关键字"create"和"copy"的函数创建的对象的count都是1, 同时真正的拥有这个对象,对象具体的生命周期要看变量什么时候使用CFRelease函数,如果在一个作用域内"create"或是"copy"一个对象, 但不调用CFRelease,这会导致count永远不能为0,也就是说当你不再需要这个对象的时候,这个对象的资源也是不会被释放的,这样就导致了内存泄露,因此,在任何地方使用了"create"和"copy"类的函数,都要记得在适当的时候进行CFRelease.
例子1:
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
{
CFStringRef ori =CFStringCreateWithCString(kCFAllocatorDefault,"hello world",kCFStringEncodingISOLatin1);
NSLog(@"ori string is :%@", ori);
CFRelease(ori);
}
}
输出结果:2016-12-15 15:23:27.246 arctest[68228:4877964] ori string is :hello world
例子2:
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
{
CFStringRef ori =CFStringCreateWithCString(kCFAllocatorDefault,"hello world",kCFStringEncodingISOLatin1);
NSLog(@"before release ori address is :%p", ori);
CFRelease(ori);
NSLog(@"after release ori address is :%p", ori);
NSLog(@"ori string is :%@", ori);
}
}
输出结果:
2016-12-15 15:36:11.892 arctest[68889:4885433] before release ori address is :0x60000003f8e0
2016-12-15 15:36:11.892 arctest[68889:4885433] after release ori address is :0x60000003f8e0
当nslog打印输出的时候,进程core了,这个是因为在打印之前已经对ori做了CFRelease处理,由于在CFRelease之前没有对ori的任何引用,也就是说引用计数器count的值一直是1,当CFRelease之后,这个count就变成了0,ARC就释放了ori的资源,导致nslog访问ori对象时core了,这里注意,通过打印日志可以看出,ARC对CF指针的处理并不像cocoa一样,cocoa的对象的指针会被ARC设置成0,但CF的指针还是不变的,也就是说在ARC处理之后,这个指针变成了一个野指针,如果有判断if(ori),这样的语句,会出很大的问题.(有同学说,CFStringRef看字面意思并不是指针啊,更像是一个对象,其实你可以在xcode下看一下它的定义typedefconststruct CF_BRIDGED_TYPE(NSString) __CFString * CFStringRef;其实就是一个指针).
对于上面的代码更优雅一点的处理如下:
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
{
CFStringRef ori =CFStringCreateWithCString(kCFAllocatorDefault,"hello world",kCFStringEncodingISOLatin1);
NSLog(@"before release ori address is :%p", ori);
CFRelease(ori);
ori = nil;
NSLog(@"after release ori address is :%p", ori);
NSLog(@"ori string is :%@", ori);
}
}
输出结果:2016-12-15 15:37:19.868 arctest[68958:4886617] before release ori address is :0x608000220900
2016-12-15 15:37:19.868 arctest[68958:4886617] after release ori address is :0x0
2016-12-15 15:37:19.872 arctest[68958:4886617] ori string is :(null)
这样处理就不会core了.同时也避免了if语句的问题.
2.通过CF提供的包含有"get"关键字的函数名获取到的是对象的引用但并不增加count的值,也就是说不需要对这个变量CFRelease,要想使用get获取对象的拥有权,必须调用CFRetain函数.
3.说一下CF(Core Foundation)中的"="赋值语句.
CF中的赋值语句其实就是一个"浅引用",不会增加对象的count,(这个和cocoa中的"="不一样, cocoa中的赋值语句会增加count)这样很危险,很可能在使用这种引用的变量的时候,原始对象已经被释放了. 要解决这种问题,需要使用CFRetain, 在确定不在需要引用之后,要使用CFRelease放弃引用,如果Retain过,但没有release的话,会导致count永远不会为0,导致不需要对象的时候,不能得到正常的释怀资源, 会造成内存泄露.
例子1:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
{
CFStringRef ori = CFStringCreateWithCString(kCFAllocatorDefault,"hello world", kCFStringEncodingISOLatin1);
NSLog(@"before release ori address is :%p", ori);
CFStringRef dest = ori;
//CFRetain(dest);
CFRelease(ori);
//ori = nil;
NSLog(@"after release dest address is :%p", dest);
NSLog(@"dest string is :%@", dest);
}
}
输出结果:
2016-12-16 14:36:39.458 arctest[2254:236748] before release ori address is :0x600000029960
2016-12-16 14:36:39.458 arctest[2254:236748] after release ori address is :0x600000029960
2016-12-16 14:36:39.459 arctest[2254:236748] dest address is :0x600000029960
说明CF中资源被释放后不会把指针设置成0,这个时候ori和dest都是一个野指针.上面的代码在打印dest中的信息时core了.
解决方案:
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
{
CFStringRef ori =CFStringCreateWithCString(kCFAllocatorDefault,"hello world",kCFStringEncodingISOLatin1);
NSLog(@"before release ori address is :%p", ori);
CFStringRef dest = ori;
CFRetain(dest);
CFRelease(ori);
ori = nil;
NSLog(@"after release ori address is :%p", ori);
NSLog(@"dest address is :%p", dest);
NSLog(@"dest string is :%@", dest);
CFRelease(dest);
dest = nil;
}
}
输出结果:2016-12-16 14:43:28.538 arctest[2321:246016] before release ori address is :0x60000003b420
2016-12-16 14:43:28.538 arctest[2321:246016] after release ori address is :0x0
2016-12-16 14:43:28.538 arctest[2321:246016] dest address is :0x60000003b420
2016-12-16 14:43:28.538 arctest[2321:246016] dest string is :hello world