Objective c [AVAssetWriterInput RequestMediaDataWhenRepayonQueue:usingBlock:]内存问题

Objective c [AVAssetWriterInput RequestMediaDataWhenRepayonQueue:usingBlock:]内存问题,objective-c,ios,memory-management,avfoundation,Objective C,Ios,Memory Management,Avfoundation,我正在编写一个库,使用AVFoundation将资产导出到文件中。我创建了一个读写器,将输入和输出连接到它们,然后在输入上调用requestMediaDataWhenRepayonQueue方法来开始提取数据。提供给此方法的块回调看起来有点像: [input requestMediaDataWhenReadyOnQueue:queue usingBlock:^{ while ([input isReadyForMoreMediaData]) { CMSampleBuffe

我正在编写一个库,使用AVFoundation将资产导出到文件中。我创建了一个读写器,将输入和输出连接到它们,然后在输入上调用
requestMediaDataWhenRepayonQueue
方法来开始提取数据。提供给此方法的块回调看起来有点像:

[input requestMediaDataWhenReadyOnQueue:queue usingBlock:^{
    while ([input isReadyForMoreMediaData]) {
        CMSampleBufferRef buffer;
        // The track has some more data for us
        if ([reader status] == AVAssetReaderStatusReading
               && (buffer = [output copyNextSampleBuffer])) {
            BOOL result = [input appendSampleBuffer:buffer];
            CFRelease(buffer);
            if (!result) {
                // handle error
                break;
            }
        // The track is finished, for whatever reason
        } else {
            [input markAsFinished]; ⬅
            switch ([reader status]) {
                // inspect the status and act accordingly
            }
        }
    }
}];
这在iOS 5上非常有效,但在iOS 4上,代码在标记为⬅ 箭。经过一些拨弄后,我觉得在将输入标记为完成后,该块立即以某种方式被破坏了。执行错误行之前完全有效的
self
指针不知何故会变成
0xfff…
或调试器报告的一些垃圾值。但是之前指向它的对象是好的,正如僵尸工具所确认的,它不会被释放

我遗漏了什么?

看到了相同(类似)的问题。iOS5快乐,iOS4.3.5,不快乐。有兴趣了解你最终发现了什么

通过在requestmeDatWhenRepayonQueue块之前显式保留writer、writer输入、reader、reader输出,并在else子句的末尾显式释放所有四个,解决了这个问题

医生说标记完成后,“块应该退出。”也许他们不是在开玩笑。如果您不执行退出操作,则这是一个错误。不过,上述解决方法似乎有效


更新:我仍然发现,即使在保留和释放所有资产对象之后,它偶尔也会崩溃。正如您的问题所观察到的,在您将writer输入标记为finished后不久,它就会崩溃,就好像块本身正在被释放一样。而不仅仅是将块作为函数的一部分传递。我创建了一个复制的块特性,该特性是长寿命对象的一部分。我用Block_copy初始化它,只在长寿命对象的析构函数中释放它。这似乎奏效了。从那以后,我再也没有见过任何4.3.5崩溃。

尝试将[self-retain]作为块的第一行,将[self-release]作为块的最后一行

另一个关键问题是,如果应用程序在READYONQUEUE时使用RequestMediaDataWhen挂起(进入后台),则需要显式覆盖所有[reader status]值,因为当应用程序重新启动时,它将失败。在某些情况下,我发现该块在带有失败状态标志的情况下运行了多次。在其他类似代码的帖子中,有很多AV变量被保留,然后在代码块的末尾被释放。因为块可以运行多次,所以当应用程序进入后台状态时,这种方法不起作用

我发现以下内容在“切换”(上图)中效果良好:


除了“自我”,什么都不保留。如果需要,程序块应自动保留变量。

您能发布此解决方案的代码吗?有同样的问题。你解决了这个问题吗?
                case AVAssetReaderStatusReading:
                    break;

                case AVAssetReaderStatusCompleted:
                    [videoWriterInput markAsFinished];
                    //do something else, like add an audio stream
                    [videoWriter finishWriting];
                    break;

                case AVAssetReaderStatusFailed:
                    [videoWriterInput markAsFinished];
                    [videoWriter finishWriting];
                    break;

                case AVAssetReaderStatusCancelled:
                case AVAssetReaderStatusUnknown:
                    [videoWriterInput markAsFinished];
                    [videoWriter cancelWriting];
                    break;
            }

            dispatch_sync(dispatch_get_main_queue(), ^{
              //hide any progress indicators
            });

            break;