由_layer.contents = (__bridge id)image.CGImage想到的

本文探讨了Objective-C中UIImage与CGImageRef之间的关系及其内存管理方式。通过实验验证了当将CGImageRef赋值给CALayer的contents属性时,CGImageRef会被retain的事实。并进一步解释了CGImageRef如何被视为NSObject子类,从而能够使用Core Foundation的引用计数机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先从这段代码说起

UIImage *image = [UIImage imageNamed:@"xxx.png"] ;
_layer.contents = (__bridge id)image.CGImage ;

我曾经考虑要不要保持image的强引用以防其被释放,因为我的理解是:image被释放时,image.CGImage就会被释放了,然而事实是image.CGImage是不会被释放的,因为_layer.contents保持了CGImage的强引用,在CALayercontents属性被定义成@property(strong) id contents;,不过我还是怀疑这个strong会起作用么?理由是,image.CGImageCGImageRef类型的,而CGImageRef是一个指针:typedef struct CGImage *CGImageRef;,我查了一下文档,发现CGImageRef不是Toll Free Bridging。_layer.contents = (__bridge id)image.CGImage ;,在这段代码执行时会给image.CGImage发送retain消息,问题是image.CGImage会被retain么?

先说结论吧,答案是会被retain,Core Foundation也是采用引用计数的机制,并且CGImageRef跟Objective-C中的NSObject *是类似的,既是CGImageNSObject类似。

当我把_layer.contents用NSLog打印出来之后,事情变得明确一些了,日志是这样:
NSLog(@"_layer.contents %@", [(__bridge id)image.CGImage class]);
结果是:
_layer.contents __NSCFType
日志说明,CGImage是有isa指针的,并且指向了一个名为__NSCFType的对象,通过调用这个函数class_getSuperclass(class),我看到__NSCFType的父类是NSObject,所以CGImage可以被看做是NSObject对象,或者说所有的Core Foundation中的类型都可以看做NSObject对象。这里我推荐看一下MikeAsh的文章,看过之后你也应该明白了。

总结一下,我产生这个疑问的原因是没搞明白Core Foundation对象的结构,虽然不是所有的Core Foundation的类型都是Toll Free Bridging的,但是他们都有着与NSObject类似的内存结构,都可以对其retain或者release。正因为这样,我们才可以对其应用__bridge或者__bridge_transfer,你可以尝试随便对一个int *类型的值应用__bridge id转换,编译器是不允的。

int *a ;
_layer.contents = (__bridge id)a ;

而下面的代码就可以编译通过:

struct {
    void *isa ;
} SimulateNSObject ;

- (void)fun
{
    struct SimulateNSObject *a ;
    _layer.contents = (__bridge id)a ; // 允许
}
AVCaptureConnection *videoConnection = [self.ImageOutPut connectionWithMediaType:AVMediaTypeVideo]; UIDeviceOrientation curDeviceOrientation = [[UIDevice currentDevice] orientation]; AVCaptureVideoOrientation avcaptureOrientation = [self avOrientationForDeviceOrientation:curDeviceOrientation]; [videoConnection setVideoOrientation:avcaptureOrientation]; [videoConnection setVideoScaleAndCropFactor:self.effectiveScale]; if (!videoConnection || !self.session.isRunning) { ATLog(@"take photo failed!"); return; } MJWeakSelf; [self.ImageOutPut captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ if (imageDataSampleBuffer) { NSData * imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]; weakSelf.image = [UIImage imageWithData:imageData]; if (weakSelf.image) { weakSelf.image = [UIImage updateImageSize:weakSelf.image]; } weakSelf.image = [[TZImageManager manager] fixOrientation:weakSelf.image];//[UIImage fixOrientation:weakSelf.image]; PHAuthorizationStatus authorStatus = [PHPhotoLibrary authorizationStatus]; if (authorStatus == PHAuthorizationStatusAuthorized) { [[TZImageManager manager] savePhotoWithImage:weakSelf.image completion:^(PHAsset *asset, NSError *error) { [weakSelf addPHAsset:asset]; }]; }else{ [weakSelf gotoEditImageController:weakSelf.image asset:nil]; } } }); }];优化此代码
最新发布
07-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值