AVAsset loadValuesAsynchronouslyForKeys:completionHandler永远不会执行

时间:2018-02-10 05:27:36

标签: ios objective-c avfoundation photosframework

这个问题已经在这里进行了几次,但我仍然没有在任何地方看到任何答案。这已经杀了我几个小时了,我在这里得到一些帮助。我有以下代码:

NSURL *url = [NSURL URLWithString:sourceVideoName];
NSDictionary *options = @{ AVURLAssetPreferPreciseDurationAndTimingKey: @YES };

PHFetchResult *ph_fetch = [PHAsset fetchAssetsWithALAssetURLs:@[url] options:nil];
PHAsset *ph_asset = [ph_fetch firstObject];

RCTLogInfo(@"Now we have PHAsset:\n%@", ph_asset);

[[PHImageManager defaultManager] requestAVAssetForVideo:ph_asset options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {

  RCTLogInfo(@"Now we have AVAsset:\n%@", asset);

  NSError *error = nil;
  AVKeyValueStatus tracksStatus = [asset statusOfValueForKey:@"tracks" error:&error];

  switch (tracksStatus) {
    case AVKeyValueStatusCancelled:
      [self log:@"Early Tracks Canceled"];
      break;
    case AVKeyValueStatusLoading:
      [self log:@"Early Tracks Loading"];
      break;
    case AVKeyValueStatusLoaded:
      [self log:@"Early Tracks Loaded"];
      break;
    case AVKeyValueStatusFailed:
      [self log:@"Early Tracks Failed"];
      break;
    case AVKeyValueStatusUnknown:
      [self log:@"Early Tracks Unknown"];
      break;
  }

  [asset loadValuesAsynchronouslyForKeys:@[@"tracks", @"duration"] completionHandler:^() {
    RCTLogInfo(@"We finally have a track callback???");
  }];

}];

当然,我们从未真正执行最终的回调。我不知道为什么也不知道如何解决它。

1 个答案:

答案 0 :(得分:0)

对我的问题的评论让我深入了解答案。基本版本是在回调执行之前,asset似乎从内存中释放出来。

ARC为属性提供了更强的内存保留,因此这可以通过添加到标题中的接口定义来实现:

@property AVAsset *asset;
@property PHAsset *photoAsset;

并将上述问题中的代码转换为:

NSURL *url = [NSURL URLWithString:sourceVideoName];
NSDictionary *options = @{ AVURLAssetPreferPreciseDurationAndTimingKey: @YES };

PHFetchResult *ph_fetch = [PHAsset fetchAssetsWithALAssetURLs:@[url] options:nil];
[self setPhotoAsset:[ph_fetch firstObject]];

RCTLogInfo(@"Now we have instance PHAsset:\n%@", [self photoAsset]);

[[PHImageManager defaultManager] requestAVAssetForVideo:[self photoAsset] options:nil resultHandler:^(AVAsset * _Nullable localAsset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {

  RCTLogInfo(@"Now we have local AVAsset:\n%@", localAsset);
  [self setAsset:localAsset];
  RCTLogInfo(@"Now we have instance AVAsset:\n%@", [self asset  ]);

  NSError *error = nil;
  AVKeyValueStatus tracksStatus = [[self asset] statusOfValueForKey:@"tracks" error:&error];

  switch (tracksStatus) {
    case AVKeyValueStatusCancelled:
      [self log:@"Early Tracks Canceled"];
      break;
    case AVKeyValueStatusLoading:
      [self log:@"Early Tracks Loading"];
      break;
    case AVKeyValueStatusLoaded:
      [self log:@"Early Tracks Loaded"];
      break;
    case AVKeyValueStatusFailed:
      [self log:@"Early Tracks Failed"];
      break;
    case AVKeyValueStatusUnknown:
      [self log:@"Early Tracks Unknown"];
      break;
  }

  [[self asset] loadValuesAsynchronouslyForKeys:@[@"tracks", @"duration"] completionHandler:^() {
    RCTLogInfo(@"We finally have a track callback!!!");
  }];

}];