当我使用静态方法从资产对象获取图像 exif 字典时发生内存泄漏,
it happened a memory leaks when I getting image exif dictionary from a asset object using a static method,
以下是导致内存泄漏的方法调用树
//get the exif info of image asset background
@autoreleasepool {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
self.dataSource = [NSMutableArray new];
__weak typeof(self) weakSelf = self;
dispatch_async(queue, ^{
for (int i = 0; i < self.selectImageList.count; i++) {
PFALAssetImageItemData *dataEntity = weakSelf.selectImageList[i];
//getting the object usering an image asset
ImageExifInfoEntity *imageExifEntity = [ImageExifInfoEntity getAlbumImageFromAsset:dataEntity.imageAsset imageOryder:i];
LOG(@"%@",imageExifEntity.description);
[weakSelf.dataSource addObject:imageExifEntity];
}
//back main thread update views
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
[self hideHud];
});
});
}
在这段代码中,我想使用静态方法和线程中的资产创建 ImageExifInfoEntity:
[ImageExifInfoEntity getAlbumImageFromAsset:dataEntity.imageAsset imageOryder:i];
该方法新建一个ImageExifInfoEntity类型的对象,并通过静态方法获取exif Dictionary
+(ImageExifInfoEntity *)getAlbumImageFromAsset:(ALAsset *)asset category:(NSString *)category imageOryder:(NSInteger)imageOrder{
ImageExifInfoEntity *albumImage = [ImageExifInfoEntity new];
..........
albumImage.imageSize = [UIImage imageSizeWithAlasset:asset];
albumImage.exifDic = [ImageExifInfoEntity getExifInfoFromAsset:asset] == nil ? @{}:[ImageExifInfoEntity getExifInfoFromAsset:asset];
..........
}
最后,我在发生内存泄漏的地方使用这种方法得到了一个 exif 字典
+(NSDictionary *)getExifInfoFromAsset:(ALAsset *)asset {
NSDictionary *_imageProperty;
__weak ALAsset *tempAsset = asset;
ALAssetRepresentation *representation = tempAsset.defaultRepresentation;
uint8_t *buffer = (uint8_t *)malloc(representation.size);
NSError *error;
NSUInteger length = [representation getBytes:buffer fromOffset:0 length:representation.size error:&error];
NSData *data = [NSData dataWithBytes:buffer length:length];
CGImageSourceRef cImageSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(cImageSource, 0, NULL);
_imageProperty = (__bridge_transfer NSDictionary*)imageProperties;
free(buffer);
NSLog(@"image property: %@", _imageProperty);
return _imageProperty;
}
这是仪器分析结果
将__bridge
替换为__bridge_transfer
,这样ARC就会负责释放内存
我觉得你应该打电话给CFRelease(cImageSource);
来发布图片来源。见文件:https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CGImageSource/#//apple_ref/c/func/CGImageSourceCreateWithData
An image source. You are responsible for releasing this object using CFRelease.
CGImageSourceCreateWithData()
是创建函数。
CGImageSourceRef cImageSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
根据CF内存规则,必须用CFRelease()
释放。
以下是导致内存泄漏的方法调用树
//get the exif info of image asset background
@autoreleasepool {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
self.dataSource = [NSMutableArray new];
__weak typeof(self) weakSelf = self;
dispatch_async(queue, ^{
for (int i = 0; i < self.selectImageList.count; i++) {
PFALAssetImageItemData *dataEntity = weakSelf.selectImageList[i];
//getting the object usering an image asset
ImageExifInfoEntity *imageExifEntity = [ImageExifInfoEntity getAlbumImageFromAsset:dataEntity.imageAsset imageOryder:i];
LOG(@"%@",imageExifEntity.description);
[weakSelf.dataSource addObject:imageExifEntity];
}
//back main thread update views
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
[self hideHud];
});
});
}
在这段代码中,我想使用静态方法和线程中的资产创建 ImageExifInfoEntity:
[ImageExifInfoEntity getAlbumImageFromAsset:dataEntity.imageAsset imageOryder:i];
该方法新建一个ImageExifInfoEntity类型的对象,并通过静态方法获取exif Dictionary
+(ImageExifInfoEntity *)getAlbumImageFromAsset:(ALAsset *)asset category:(NSString *)category imageOryder:(NSInteger)imageOrder{
ImageExifInfoEntity *albumImage = [ImageExifInfoEntity new];
..........
albumImage.imageSize = [UIImage imageSizeWithAlasset:asset];
albumImage.exifDic = [ImageExifInfoEntity getExifInfoFromAsset:asset] == nil ? @{}:[ImageExifInfoEntity getExifInfoFromAsset:asset];
..........
}
最后,我在发生内存泄漏的地方使用这种方法得到了一个 exif 字典
+(NSDictionary *)getExifInfoFromAsset:(ALAsset *)asset {
NSDictionary *_imageProperty;
__weak ALAsset *tempAsset = asset;
ALAssetRepresentation *representation = tempAsset.defaultRepresentation;
uint8_t *buffer = (uint8_t *)malloc(representation.size);
NSError *error;
NSUInteger length = [representation getBytes:buffer fromOffset:0 length:representation.size error:&error];
NSData *data = [NSData dataWithBytes:buffer length:length];
CGImageSourceRef cImageSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(cImageSource, 0, NULL);
_imageProperty = (__bridge_transfer NSDictionary*)imageProperties;
free(buffer);
NSLog(@"image property: %@", _imageProperty);
return _imageProperty;
}
这是仪器分析结果
将__bridge
替换为__bridge_transfer
,这样ARC就会负责释放内存
我觉得你应该打电话给CFRelease(cImageSource);
来发布图片来源。见文件:https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CGImageSource/#//apple_ref/c/func/CGImageSourceCreateWithData
An image source. You are responsible for releasing this object using CFRelease.
CGImageSourceCreateWithData()
是创建函数。
CGImageSourceRef cImageSource = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
根据CF内存规则,必须用CFRelease()
释放。