LoadValuesAsynchronouslyForKeys and several load values

I would like to asynchronously load the duration, time (timestamp that the video created) and the locale of the object.

All of the code sample shown by Apple to use 'loadValuesAsynchronouslyForKeys:keys' always shows only one key. i.e:

 NSURL *url = aUrl; AVAsset asset = [[AVURLAsset alloc] initWithURL:url options:nil]; NSArray *keys = [NSArray arrayWithObject:@"duration"]; [asset loadValuesAsynchronouslyForKeys:keys completionHandler:^() { NSError *error = nil; AVKeyValueStatus durationStatus = [asset statusOfValueForKey:@"duration" error:&error]; switch (durationSatus) { case AVKeyValueStatusLoaded: // Read duration from asset CMTime assetDurationInCMTime = [asset duration]; break; case AVKeyValueStatusFailed: // Report error break; case AVKeyValueStatusCancelled: // Do whatever is appropriate for cancelation } }]; 

Can I assume that if one element has the status "AVKeyValueStatusLoaded", other values ​​can be read simultaneously in the completion block? i.e:

 [asset tracks] [asset commonMetadata]; [asset duration] 
+6
source share
2 answers

No, you cannot allow this. One of my methods looks at two keys, playability and duration, and I found that playable is often available, but duration has not yet been reached. I therefore moved loadValuesAsynchronouslyForKeys: code into a separate shouldSave: method. The shouldSave method: I call from the timer in the saveWithDuration: method. As soon as saveWithDuration: gets a nonzero duration, it goes ahead and saves the material. To avoid waiting too long, I use the counter of attempts at the moment - in the future, I will clarify this (you will notice that the error instance is not currently used)

 - (void)shouldSave:(NSTimer*)theTimer { NSString * const TBDuration = @"duration"; NSString * const TBPlayable = @"playable"; __block float theDuration = TBZeroDuration; __block NSError *error = nil; NSArray *assetKeys = [NSArray arrayWithObjects:TBDuration, TBPlayable, nil]; [_audioAsset loadValuesAsynchronouslyForKeys:assetKeys completionHandler:^() { AVKeyValueStatus playableStatus = [_audioAsset statusOfValueForKey:TBPlayable error:&error]; switch (playableStatus) { case AVKeyValueStatusLoaded: //go on break; default: return; } AVKeyValueStatus durationStatus = [_audioAsset statusOfValueForKey:TBDuration error:&error]; switch (durationStatus) { case AVKeyValueStatusLoaded: theDuration = CMTimeGetSeconds(_audioAsset.duration); break; default: return; } }]; NSUInteger attempt = [[[theTimer userInfo] objectForKey:TBAttemptKey] integerValue]; attempt++; [self saveWithDuration:theDuration attempt:attempt error:&error]; 

}

+6
source

Technically, you cannot. docs for loadValuesAsynchronouslyForKeys: completeHandler: says that

The completion status of the keys you specify is not necessarily the same β€” some may be loaded and others may have failed. You must check the status of each key individually.

In practice, I think this is often a safe assumption - as you already noted, the Apple StitchedStreamPlayer sample project just looks at the state of the first key.

+2
source

Source: https://habr.com/ru/post/890969/


All Articles