Ios4 iOS内存泄漏使用AVAssetWriter从图像创建视频

Ios4 iOS内存泄漏使用AVAssetWriter从图像创建视频,ios4,instruments,automatic-ref-counting,avassetwriter,Ios4,Instruments,Automatic Ref Counting,Avassetwriter,我对iOS开发和stackoverflow都是新手,所以如果我的代码看起来不像应该的那么好,请原谅我。我已经使用ARC和AVAssetWriter创建了一个测试应用程序,用我的应用程序包中的图像创建视频。一切正常,视频也正常创建,但当我用仪器评测我的应用程序时,我发现内存泄漏,我真的不知道如何修复,因为我在详细视图中看不到与我的代码相关的任何内容(所有泄漏的对象都是Malloc,负责的库是VideoToolbox).以下是我在视图控制器类中开始编写视频时调用的方法: 下面是我用来获取像素缓冲


我对iOS开发和stackoverflow都是新手,所以如果我的代码看起来不像应该的那么好,请原谅我。

我已经使用ARC和
AVAssetWriter创建了一个测试应用程序,用我的应用程序包中的图像创建视频。一切正常,视频也正常创建,但当我用仪器评测我的应用程序时,我发现内存泄漏,我真的不知道如何修复,因为我在详细视图中看不到与我的代码相关的任何内容(所有泄漏的对象都是Malloc,负责的库是
VideoToolbox
).

以下是我在视图控制器类中开始编写视频时调用的方法:


下面是我用来获取像素缓冲区以附加到前面方法中实例化的像素缓冲区适配器的方法:


我发现内存泄漏与视频编写代码无关。泄漏的代码似乎是我在
-(void)writeVideo


中调用的
[self deleteTempVideo]
方法,我仍然需要找出它的错误,但我想我的问题在这一点上超出了范围。
以下是
-(void)deleteTempVideo
的代码:

-(无效)删除临时视频
{
NSFileManager*fileManager=[NSFileManager defaultManager];
if([fileManager isReadableFileAtPath:self.videoPath])[fileManager removietematpath:self.videoPath错误:nil];
}
下面是我用来访问self.videoPath@property的getter:

-(NSString*)视频路径
{
如果(!\u视频路径){
NSString*fileName=@“test.mov”;
NSString*directoryPath=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES)lastObject];
_videoPath=[directoryPath stringByAppendingPathComponent:fileName];
}
返回视频路径;
}

根据我的经验,当您同时使用arc和block时, 您不应该直接使用成员变量。 相反,可以使用弱属性

假设您有一个名为ClassA的类和一个名为_memberA的成员变量。 通常我会定义memberA的一个属性,然后我可以像下面那样编写代码

__weak ClassA *weakSelf = self;
SomeVariable.function = ^() {
    weakSelf.memberA ..... (not use _memberA Here)
}
附言。 如果该块来自某个静态函数,如[UIView动画:持续时间:完成:],则在使用成员变量时似乎可以


我用这种方法解决了很多内存泄漏问题。

AVAssetWriter*writer从未被释放。@Allyn:也许我遗漏了一些东西,但既然我使用了ARC,我该如何释放AVAssetWriter*writer?啊,对不起,我遗漏了您使用的ARC。在这种情况下,可能您永远不会发布CVReturn结果-我认为ARC不会处理这个问题。对不起,Allyn,但据我所知(我知道的不多),CVReturn是一个int,所以不应该发布。
// Consume the imageNamesCopy mutable array and return a CVPixelBufferRef relative to the last object of the array
- (CVPixelBufferRef)fetchNextPixelBuffer
{
    NSString *imageName = [self.imageNamesCopy lastObject];
    if (imageName) [self.imageNamesCopy removeLastObject];
    // Create an UIImage instance
    UIImage *image = [UIImage imageNamed:imageName];
    CGImageRef imageRef = image.CGImage;    

    CVPixelBufferRef buffer = NULL;
    size_t width = CGImageGetWidth(imageRef);
    size_t height = CGImageGetHeight(imageRef);
    // Pixel buffer options
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, 
                             [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil];
    // Create the pixel buffer
    CVReturn result = CVPixelBufferCreate(NULL, width, height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef) options, &buffer);
    if (result == kCVReturnSuccess && buffer) {
        CVPixelBufferLockBaseAddress(buffer, 0);
        void *bufferPointer = CVPixelBufferGetBaseAddress(buffer);
        // Define the color space
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        // Create the bitmap context to draw the image
        CGContextRef context = CGBitmapContextCreate(bufferPointer, width, height, 8, 4 * width, colorSpace, kCGImageAlphaNoneSkipFirst);
        CGColorSpaceRelease(colorSpace);
        if (context) {
            CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
            CGContextRelease(context);
        }
        CVPixelBufferUnlockBaseAddress(buffer, 0);
    }
    return buffer;
}
__weak ClassA *weakSelf = self;
SomeVariable.function = ^() {
    weakSelf.memberA ..... (not use _memberA Here)
}