iphone - objective - framework ios
Barra de progreso para AVAssetExportSession (4)
Tengo una aplicación que exporta AVMutableComposition
en un archivo .mov
, y me gustaría que el usuario vea el estado de la exportación con una barra de progreso de la misma forma que lo haría si enviara un mensaje de texto o subiera un expediente.
Sé cómo crear una barra de progreso cuando sé la duración de una tarea (como reproducir un archivo de audio), pero como no hay una duración establecida para la exportación, no estoy seguro de cómo proceder.
Actualmente tengo un indicador de actividad, pero no proporciona la mejor experiencia de usuario.
¿Alguien tiene algún puntero?
Ejemplo de Swift 3
Uso del Centro de notificaciones para enviar actualizaciones de progreso a los oyentes
//`AVAssetExportSession` code above
var exportProgressBarTimer = Timer() // initialize timer
if #available(iOS 10.0, *) {
exportProgressBarTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
// Get Progress
let progress = Float((exportSession?.progress)!);
if (progress < 0.99) {
let dict:[String: Float] = ["progress": progress]
NotificationCenter.default.post(name: Notification.Name("ProgressBarPercentage"), object: nil, userInfo: dict)
}
}
}
// on exportSession completed
exportSession?.exportAsynchronously(completionHandler: {
exportProgressBarTimer.invalidate(); // remove/invalidate timer
if exportSession?.status == AVAssetExportSessionStatus.completed {
// [....Some Completion Code Here]
}
})
A continuación, configure el servicio de escucha del centro de notificaciones en cualquier lugar que desee utilizar.
NotificationCenter.default.addObserver(self, selector: #selector(self.statusUpdate(_:)), name: NSNotification.Name(rawValue: "ProgressBarPercentage"), object: nil)
El mismo problema que he enfrentado en iOS 8.0, lo resolví usando la cola de despacho
- (void)convertVideoToLowQuailtyWithInputURL:(NSURL*)inputURL outputURL:(NSURL*)outputURL handler:(void (^)(AVAssetExportSession*))handler{
[[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:inputURL options:nil];
exportSession2 = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetLowQuality];
exportSession2.outputURL = outputURL;
exportSession2.outputFileType = AVFileTypeQuickTimeMovie;
[exportSession2 exportAsynchronouslyWithCompletionHandler:^(void)
{
handler(exportSession2);
}];
dispatch_async(dispatch_get_main_queue(), ^(void){
self.exportProgressBarTimer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(updateExportDisplay) userInfo:nil repeats:YES];
});
}
Se me ocurrió una respuesta hace un tiempo, así que la publicaré en caso de que pueda ayudar a alguien:
Primero, en el método en el que llama a AVAssetExportSession
, debe configurar un temporizador para actualizar su UIProgressView
una vez que haya iniciado la exportación:
//`AVAssetExportSession` code here
self.exportProgressBarTimer = [NSTimer scheduledTimerWithTimeInterval:.1 target:self selector:@selector(updateExportDisplay) userInfo:nil repeats:YES];
...
Entonces necesita un método para actualizar su pantalla teniendo en cuenta que la propiedad de progreso en AVAssetExportSession
va de 0 a 1:
- (void)updateExportDisplay {
self.exportProgressBar.progress = exportSession.progress;
if (self.exportProgressBar.progress > .99) {
[self.exportProgressBarTimer invalidate];
}
}
Use las siguientes líneas de código.
AVAssetExportSession *session = [AVAssetExportSession exportSessionWithAsset:composition presetName:AVAssetExportPresetMediumQuality];
self.exportSession = session;
// 出力先(テンポラリファイル)の設定。
NSString *filePath = NSTemporaryDirectory();
filePath = [filePath stringByAppendingPathComponent:@"out.mov"];
[[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
session.outputURL = [NSURL fileURLWithPath:filePath];
// 出力タイプの設定。
session.outputFileType = AVFileTypeQuickTimeMovie;
// 非同期エクスポートの開始。
[session exportAsynchronouslyWithCompletionHandler:^{
if (session.status == AVAssetExportSessionStatusCompleted) {
// フォトアルバムへの書き込み。
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:session.outputURL completionBlock:^(NSURL *assetURL, NSError *error){
if (error) {
self.resultLabel.text = [NSString stringWithFormat:@"アセット書き込み失敗/n%@", error];
} else {
self.resultLabel.text = [NSString stringWithFormat:@"完了/n%@", assetURL];
}
}];
[library autorelease];
} else if (session.status == AVAssetExportSessionStatusCancelled) {
self.resultLabel.text = @"エクスポート中断";
} else {
self.resultLabel.text = [NSString stringWithFormat:@"エクスポート失敗/n%@", session.error];
}
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
while (session.status == AVAssetExportSessionStatusExporting) {
dispatch_sync(dispatch_get_main_queue(), ^{
self.progressView.progress = session.progress;
});
}
});
Enlace de referencia: https://github.com/keijiro/iOS4BookSampleCode/blob/master/3.3.SimpleExport/Classes/SimpleExportViewController.m