loadValuesAsynchronouslyForKeys和多个值加载

时间:2011-06-21 00:32:12

标签: iphone objective-c ios4 avfoundation

我想异步加载持续时间,时间(创建视频的时间戳)和资产的区域设置。

Apple显示的'loadValuesAsynchronouslyForKeys:keys'使用的所有示例代码始终只显示一个键。即:

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   
    }
}];

我可以假设如果一个项目的状态是'AVKeyValueStatusLoaded',那么在完成块中可以同时读取其他值吗?即:

[asset tracks]
[asset commonMetadata];
[asset duration]

3 个答案:

答案 0 :(得分:6)

不,你不能这么认为。我的一种方法看了两个键,可玩和持续时间,我发现可玩性通常可用,而持续时间尚未。我因此将loadValuesAsynchronouslyForKeys:代码移动到一个单独的方法shouldSave:。我在一个叫做save​​WithDuration:的方法中从一个计时器调用的shouldSave:方法。一旦saveWithDuration:收到非零持续时间,它就会继续并保存东西。为了避免等待太久,我现在使用一个尝试计数器 - 将来,我会改进这个(你会注意到错误实例目前还没有使用)

- (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];

}

答案 1 :(得分:2)

技术上你不能。 load {docs for loadValuesAsynchronouslyForKeys:completionHandler:表示

  

你的钥匙的完成状态   在键中指定不一定   相同的 - 一些可能被加载,和   其他人可能都失败了。你必须检查   每个密钥的状态。

在实践中,我认为这通常是一个安全的假设 - 正如您所指出的,Apple的StitchedStreamPlayer示例项目只是查看第一个键的状态。

答案 2 :(得分:0)

不,您不能这样假设。我通常依靠@"duration"键来创建AVPlayerItem并开始播放,因为加载@"playable"通常不能保证资产已经准备就绪。然后,我产生了一个计时器,以定期检查是否加载了其他密钥,例如@"tracks",类似于上面提到的Elise van Looij。

此外,请注意-切记completionHandler中的loadValuesAsynchronouslyForKeys是在任意后台线程上调用的。如果要处理UI或AVPlayerLayer,则必须将其分派到主线程。