2013-09-14 4 views
18

Я использую AVAssetWriter, и он отлично работает на iOS6.Обработчик завершения не вызывается на iOS7 GM

Проблема в том, что когда я позвонил finishWritingWithCompletionHandler, обработчик завершения не вызывается на iOS7 GM.

Я позвонил markAsFinished, и даже endSessionAtSourceTime, прежде чем я позвоню finishWritingWithCompletionHandler.

Он отлично работает на iOS6.

И даже больше, на iOS7, он работает несколько раз, а затем он не работает снова.

Я не знаю почему, но он работает, если я вызываю метод с использованием вида предупреждения. Так что я пробовал performSelectorOnMainThread и inBackground, но это не помогло.

Любые идеи?

ответ

38

По-видимому, вам необходимо сохранить ресурс.

Вы можете попытаться сохранить с сильным свойством и посмотреть, вызван ли ваш обработчик завершения. (Обязательно забудьте это свойство в обработчике завершения.)

+0

Спасибо за ваш ответ. Я попробую и дам вам знать. –

+2

Это прекрасно работает. Благодаря! –

+0

Спасибо. Это меня разочаровывало. AVAssetWriter выплескивал неиграемые видео с неполными метаданными, пока не нашел этот самородок мудрости. Сейчас работает как шарм. –

8

Ray Fix, вы правы. Нам нужно сохранить assetWriter. Самый простой способ, чтобы использовать его внутри блока finishWritingWithCompletionHandler:

 NSError *error = nil; 

     AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL:[NSURL fileURLWithPath:path] 
                    fileType:AVFileType3GPP 
                     error:&error]; 
     //startWriting, session etc. 

     [videoWriter finishWritingWithCompletionHandler:^{ 
       NSLog(@"%@",videoWriter); 
       NSLog(@"Write Ended"); 
      }]; 
+1

Если закончитьНаступлениеКомплектацииГандлер не срабатывает, это просочится навсегда. Лучше использовать свойство, объявленное сильным, или убедитесь, что он не выпустит видеозаписывающее устройство, используя другой способ. – automaticoo

1

Это также может произойти, если каталог назначения не существует. В этом случае запись работает нормально, но файл не создается и блок не вызывается.

+0

Я думаю, что это то, что происходит со мной. Я пишу приложение, которое записывает несколько видеофайлов подряд, и я использую тот же код для установки новых файловURL для каждого нового видео. Иногда файл создается и вызывается блок, иначе файл пуст, и блок завершения никогда не вызывается, и мой спутник не работает на следующем видео. Я попробовал решение Рэя, но это не сработало. Вы случайно знаете, что моя проблема может быть? –

+0

Если ваш файл пуст, это означает, что вы не пишете никаких образцов, или произошла ошибка. Я предлагаю отслеживать количество образцов, успешно записанных в файл, файл пуст - не ждите обработчика. – AlexeyVMP

+0

В моем случае практически невозможно иметь пустой выходной файл, так как я выполняю транскодирование. – AlexeyVMP

3

Сохранение ассистента очень важно, но я также столкнулся с очень странным прерывистым сбоем, хотя мои ассистенты были сохранены (и никогда не использовались повторно). Проблема также заключалась не в конфликте имени файла или отсутствующем каталоге, потому что мои имена файлов основаны на CACurrentMediaTime() и не меняют каталоги.

Кажется, что вы не устанавливаете endSessionAtSourceTime: для ассемблера каждый раз, есть очень редкая (но воспроизводимая) вероятность того, что обработчик завершения для finishWritingWithCompletionHandler: никогда не будет вызван. Если вы подождете несколько секунд и проверьте статус ассистента, он будет находиться в состоянии AVAssetWriterStatusFailure, и ошибка будет не описана «Неизвестная ошибка (-12763)». Кроме того, изменение формата файла для ассистента не влияет на эту проблему. Наконец, эта проблема, вероятно, является лишь проблемой, если вам нужно быстро записывать фильмы снова и снова (поскольку вероятность неудачи, вероятно, составляет 1/15 - 1/20).

Итак, просто сохраните отметку времени представления для последнего образца, который вы передаете ассистенту, и позвоните по телефону endSessionAtSourceTime: с этим временем выборки прямо перед тем, как вы собираетесь позвонить finishWritingWithCompletionHandler:.

+0

То же самое! В случаях тяжелой записи (запись в реальном времени + запись) я вижу такое же поведение - обратный вызов не вызывается без каких-либо ошибок. Propers endSessionAtSourceTime исправил проблему, спасибо! – IPv6

3

Это происходит и на ARC.

Самое простое решение состоит в определении свойств AVAssetWriter (и AVAssetReader я предполагаю)

@property(nonatomic,strong) AVAssetWriter *assetWriter; 
@property(nonatomic,strong) AVAssetReader *assetReader; 

, а затем

self.assetWriter = [AVAssetWriter assetWriterWithURL:destURL 
                 fileType:AVFileTypeWAVE 
                  error:&assetError]; 

и в блоке завершения

   [assetWriterInput markAsFinished]; 
      [assetWriter finishWritingWithCompletionHandler:^{ 
       [assetReader cancelReading]; 
       completionBlock(self); 

      }]; 
Смежные вопросы