ios - 使用 block 的内存泄漏

标签 ios ipad memory-management memory-leaks avassetexportsession

我写了两个方法

  • 生成音频的
  • 另一个将音频添加到视频

我使用“AVAssetExportSession”来执行这些操作并执行一些操作 AVAssetExportSession 类的“exportAsynchronouslyWithCompletionHandler”

这是生成音频的代码

AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition 
                                                                      presetName:AVAssetExportPresetAppleM4A];   

NSString *outputUrl = [NSString stringWithFormat:@"%@/Video/%@",userDocumentsPath,@"finalAudio.m4a"];
//Specifing the output file where we want to store our fianl asset
_assetExport.outputFileType = AVFileTypeAppleM4A;
NSURL *finalUrl = [[NSURL alloc] initFileURLWithPath:outputUrl isDirectory:NO];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:finalUrl.path];
//deleting file if it exists
if (fileExists)
{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    [fileManager removeItemAtPath:finalUrl.path error:NULL];
}

_assetExport.outputURL = finalUrl;
_assetExport.shouldOptimizeForNetworkUse = YES;
_assetExport.audioMix = audioMix;
__block ICImageToVideo *temp = self;

[_assetExport exportAsynchronouslyWithCompletionHandler:
 ^(void ) 
 {
     NSString *documentsPath = nil;
     NSArray *filePaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
     if ([filePaths count] > 0) 
     {
         documentsPath = [filePaths objectAtIndex:0];
     }


     NSString *audioPath = [NSString stringWithFormat:@"%@/Video/%@",documentsPath,@"finalAudio.m4a"];

     NSURL *finalAudio = [[NSURL alloc] initFileURLWithPath:audioPath isDirectory:NO];
     temp.audioUrl = finalAudio;

     [temp addAudioToVideo];

     [finalAudio release]; 
     [_assetExport release]; 
 }];

将音频添加到视频的代码是:

- (void)addAudioToVideo
{
NSString *userDocumentsPath = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
if ([paths count] > 0) 
{
    userDocumentsPath = [paths objectAtIndex:0];
}
NSURL *videoUrl = [[NSURL alloc] initFileURLWithPath:self.videoUrl] ;

//    NSString* audio = [[NSBundle mainBundle] pathForResource:@"sample" ofType:@"mp3"];
//    NSURL *audioUrl = [[NSURL alloc] initFileURLWithPath:audio];

if (self.audioUrl || videoUrl) 
{
    NSLog(@"Found the URLs!");
}

//Used to denote an audoi/video asset taken from the url
//https://developer.apple.com/library/mac/#documentation/AVFoundation/Reference/AVURLAsset_Class/Reference/Reference.html

AVURLAsset* audioAsset = [[AVURLAsset alloc] initWithURL:self.audioUrl options:nil];
AVURLAsset* videoAsset = [[AVURLAsset alloc] initWithURL:videoUrl options:nil];

//Used to denote a set of AVCompositionMutableTrack 's to create a custom combination from combining them
//https://developer.apple.com/library/mac/#documentation/AVFoundation/Reference/AVMutableComposition_Class/Reference/Reference.html

AVMutableComposition* mixComposition = [AVMutableComposition composition];

//Used to allow us to make a low level composition of tracks
//https://developer.apple.com/library/ios/#DOCUMENTATION/AVFoundation/Reference/AVMutableCompositionTrack_Class/Reference/Reference.html
AVMutableCompositionTrack *compositionCommentaryTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio 
                                                                                    preferredTrackID:kCMPersistentTrackID_Invalid];

//Here we insert a custom asset into a track of our mutable track composition at the specified time
[compositionCommentaryTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration ) 
                                    ofTrack:[[audioAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0] 
                                     atTime:kCMTimeZero error:nil];



NSLog(@"Audio Duration : %f",CMTimeGetSeconds(audioAsset.duration));
NSLog(@"Video Duration : %f",CMTimeGetSeconds(videoAsset.duration));

int difference = CMTimeCompare(videoAsset.duration, audioAsset.duration);
NSLog(@"Difference = %d",difference);

//We create another mutable composition track to hold the video that we need to insert into our final asset
AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo 
                                                                               preferredTrackID:kCMPersistentTrackID_Invalid];
[compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration) 
                               ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0] 
                                atTime:kCMTimeZero error:nil];

AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition 
                                                                      presetName:AVAssetExportPresetPassthrough];   

NSString *outputUrl = [NSString stringWithFormat:@"%@/Video/%@",userDocumentsPath,@"final.mov"];
//Specifing the output file where we want to store our fianl asset
_assetExport.outputFileType = @"com.apple.quicktime-movie";
NSLog(@"file type %@",_assetExport.outputFileType);
NSURL *finalUrl = [[NSURL alloc] initFileURLWithPath:outputUrl isDirectory:NO];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:finalUrl.path];
//deleting file if it exists
if (fileExists)
{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    [fileManager removeItemAtPath:finalUrl.path error:NULL];
}

_assetExport.outputURL = finalUrl;
_assetExport.shouldOptimizeForNetworkUse = YES;

__block ICImageToVideo *temp = self;
[_assetExport exportAsynchronouslyWithCompletionHandler:
 ^(void ) 
 {
     NSString *documentsPath = nil;
     NSArray *filePaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
     if ([filePaths count] > 0) 
     {
         documentsPath = [filePaths objectAtIndex:0];
     }

     NSString *videopath = [NSString stringWithFormat:@"%@/Video/%@",documentsPath,@"final.mov"];
     NSLog(@"videoPAth: %@",videopath);

     BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:temp.videoUrl];
     //deleting file if it exists
     if (fileExists)
     {
         NSFileManager *fileManager = [NSFileManager defaultManager];
         [fileManager removeItemAtPath:temp.videoUrl error:NULL];

         NSURL* tempSrcURL = [[NSURL alloc] initFileURLWithPath:videopath];
         NSURL* sourceUrl = tempSrcURL;
         //[tempSrcURL release]; //[NEW LEAK FIXED]
         //NSURL *sourceUrl = [[NSURL alloc] initFileURLWithPath:videopath];

         NSURL* tempDestURL = [[NSURL alloc] initFileURLWithPath:temp.videoUrl];
         NSURL* destinationUrl = tempDestURL;
         //[tempDestURL release]; //[NEW LEAK FIXED]
         //NSURL *destinationUrl = [[NSURL alloc]initFileURLWithPath:self.videoUrl];

         [fileManager moveItemAtURL:sourceUrl toURL:destinationUrl error:nil];
         [tempSrcURL release]; //[NEW LEAK FIXED]
         [tempDestURL release]; //[NEW LEAK FIXED]
     }
     [temp.delegate didProgressVideoGenereation:1];
     [temp.delegate didFinishPreparingVideoWithUrl:self.videoUrl];
     [_assetExport release];
 }];

[audioAsset release];
[videoAsset release];
[videoUrl release];
[finalUrl release];
}

我似乎在两个/一个 block 中都出现泄漏,但我未能使用泄漏工具或静态分析器查明问题。

任何建议都会有帮助。

最佳答案

在第二个 block 中您使用 self而不是 __block temp

 [temp.delegate didFinishPreparingVideoWithUrl:self.videoUrl];

应该是

 [temp.delegate didFinishPreparingVideoWithUrl: temp.videoUrl];

然后你释放_assetExport直接在你的 block 中不要这样做,保存 _assetExport到对象变量和 release它在 dealloc方法

关于ios - 使用 block 的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10613049/

相关文章:

iphone - 如何将两个数组加载到同一个 TableView 中?

函数生成多态对象的 C++ 返回类型?

IOS Swift 自定义键盘默认系统操作

ios - 重置 iOS 7 麦克风访问权限

ios - 两分钟gps开启后,为什么设备会停止在iOS上接收位置信息?

c++ - 在 C++ 中释放内存期间,迭代器与指针有何不同

iPhone 内存管理

ios - 为什么 Facebook 能够通过 iOS 9 beta 3 中的应用邀请启动我的应用(openURL : also works)?

ios - UIPopoverController:在 popover 仍然可见时达到 dealloc

ios - 对于 iOS,如何在按钮内创建可拖动按钮?