我正在编写一个库,以便使用AVFoundation将资源导出到文件中。我创建了一个读取器,一个读取器和一个写入器,将输入和输出连接到这些,然后在输入上调用requestMediaDataWhenReadyOnQueue方法来开始提取数据。提供给此方法的块回调看起来有点像这样:
[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上,EXC_BAD_ACCESS中的代码在⬅箭头标记的行后就会死掉。在周围戳了一下之后,我感觉在将输入标记为完成后,块就被以某种方式立即销毁了。在执行坏行之前完全有效的self指针会以某种方式变成0xfff…或调试器报告的一些无用的值。但是之前指向它的对象是好的,正如僵尸工具所确认的那样,它不会被释放。
我遗漏了什么?
发布于 2012-01-24 11:47:44
看到相同(类似)的问题。iOS5快乐,iOS4.3.5,不快乐。有兴趣了解你最终找到了什么。
通过在requestMedatWhenReadyOnQueue块之前显式保留写入器、写入器输入、读取器和读取器输出,并在else子句的末尾显式释放所有四个,从而解决了这一问题。
文档中确实提到,在标记为完成之后,“该块应退出”。也许他们不是在开玩笑。如果你做了除退出之外的任何事情,那就是一个错误。不过,上面的变通方法似乎是可行的。
更新:我仍然发现它偶尔会崩溃,即使在保留和释放所有资产对象之后也是如此。正如您的问题所观察到的,在您将编写器输入标记为完成后不久,它就崩溃了,就好像块本身正在被释放一样。而不是仅仅将块作为函数的一部分进行传递。我创建了一个复制的块特性,它是long lived对象的一部分。我用Block_copy初始化它,并且只在长寿对象的析构函数中释放它。这似乎起到了作用。从那以后,我再也没有见过4.3.5崩溃。
发布于 2012-05-10 11:04:18
尝试将self retain作为块的第一行,并将self release作为最后一行。
另一个关键问题是,如果应用程序使用requestMediaDataWhenReadyOnQueue挂起(进入后台),您需要显式地覆盖所有读卡器状态值,因为它将在应用程序重启时失败。在某些情况下,我发现块运行不止一次,并带有一个失败状态标志。在其他具有类似代码的帖子中,会保留大量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;除了"self“之外,没有任何东西被保留。如果需要,块应该自动保留变量。
https://stackoverflow.com/questions/8974679
复制相似问题