When using an Objective-C object that returns asynchronously with a completion handler开发者_运维知识库, like AVAssetExportSession, is there anything wronmg with code like this:
AVAssetExportSession* exportSession = [[AVAssetExportSession alloc] initWithAsset: composition presetName: AVAssetExportPresetHighestQuality];
[exportSession exportAsynchronouslyWithCompletionHandler: ^(void) {
// export completed
NSLog(@"Export Complete %d %@", exportSession.status, exportSession.error);
[exportSession release];
}];
Instruments reports exportSession as a leak. I've also got a few classes of my own that use the same methodology and they also get reported as leaks.
From everything I've read it seems like the code should follow the proper memory management rules but something must be up. I found a link to this article, but I don't think I'm causing Cyclic Retention.
Blocks in Objective-C automatically take ownership of objects in their scope, and you do cause a cyclic reference. Your block retains exportSession
implicitly, and exportSession
likely retains your block.
Memory management rules say you should relinquish ownership of objects as soon as you can. Therefore, the right place to do it, in your case, is after the call to exportAsynchronouslyWithCompletionHandler:
.
AVAssetExportSession* exportSession = [[AVAssetExportSession alloc] initWithAsset: composition presetName: AVAssetExportPresetHighestQuality];
[exportSession exportAsynchronouslyWithCompletionHandler: ^(void) {
// export completed
NSLog(@"Export Complete %d %@", exportSession.status, exportSession.error);
}];
[exportSession release];
The cyclic reference should be obvious that way: exportSession
will be kept alive by the block, and the block itself will be kept alive by the object.
When you deal with blocks, I suggest you use the garbage collected environment.
精彩评论