【问题标题】:NSBundleResourceRequest bundlePathNSBundleResourceRequest 捆绑路径
【发布时间】:2016-07-09 08:20:39
【问题描述】:

[更新在问题的结尾]

我用来在我的应用中播放一些音频文件。

我以前将文件存储在应用程序中,但后来我搬到了On Demand ResourcesNSBundleResourceRequest

我有一个IBAction 来播放随机文件,但由于我移至ODR,它无法正常工作。我唯一改变的是NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];(第3行)

NSBundleResourceRequest *request1;

- (IBAction)randomPlay {
    NSString *bundleRoot = [[request1 bundle] bundlePath];
    NSFileManager *fm = [NSFileManager defaultManager];
    NSArray *dirContents = [fm contentsOfDirectoryAtPath:bundleRoot error:nil];
    NSPredicate *fltr = [NSPredicate predicateWithFormat:@"self ENDSWITH '.mp3'"];
    NSArray *onlyMP3s = [dirContents filteredArrayUsingPredicate:fltr];
    .
    .
    .
    audio = [onlyMP3s[arc4random_uniform((uint32_t)onlyMP3s.count)] 
            stringByReplacingOccurrencesOfString:@".mp3" withString:@""];
    [self playSelectedAudio:audio];
}

dirContents 看起来像:

当它应该包含 mp3 文件时。

bundleRoot 我做错了什么?

我的viewDidload

- (void)viewDidLoad {
 [super viewDidLoad];

 tagsSet = [NSSet setWithObjects:@"sounds", nil];
 request1 = [[NSBundleResourceRequest alloc] initWithTags:tagsSet];
 [request1 conditionallyBeginAccessingResourcesWithCompletionHandler:^
                               (BOOL resourcesAvailable) {
    if (resourcesAvailable) {
        //don't do nothing. just use the file slater
    } else {
        [request1 beginAccessingResourcesWithCompletionHandler:^
                               (NSError * _Nullable error) {
            if (error == nil) {
                //download the files
            } else {
            }
        }];
    }
}];

我实际上有另一种方法来播放选定的音频(不是随机的)

-(void)playSelectedAudio:(id)audioToPlay {
NSURL *url = [NSURL fileURLWithPath:[[request1 bundle] 
              pathForResource:audioToPlay ofType:@"mp3"]];

它工作正常。

所以bundleRoot有问题,不是我的文件所在的位置。

[更新]

我确实做到了

- (IBAction)randomPlay {
       NSURL *bundleRoot = [NSURL fileURLWithPath:[[request1 bundle] 
                            pathForResource:@"" ofType:@"mp3"]];
       NSFileManager *fm = [NSFileManager defaultManager];
       NSArray *dirContents = [fm contentsOfDirectoryAtURL:bundleRoot 
                              includingPropertiesForKeys:[NSArray array] 
                              options:0 error:nil];
        NSPredicate *fltr = [NSPredicate predicateWithFormat:
                            @"self ENDSWITH '.mp3'"];
        NSArray *onlyMP3s = [dirContents 
                            filteredArrayUsingPredicate:fltr];
        .
        .
        .
        audio = [onlyMP3s[arc4random_uniform((uint32_t)onlyMP3s.count)] 
                        stringByReplacingOccurrencesOfString:@".mp3" 
                        withString:@""];
        [self playSelectedAudio:audio];
    }];

}

它几乎可以工作,但总是在播放目录中的第一个音频。

【问题讨论】:

  • 检查你的随机数和数组计数。
  • 嘿@bbum 感谢您的回答。当我使用[NSBundle mainBundle] 时,此方法正常工作,因此从目录中的所有音频中正确选择随机音频。我应该检查哪一部分?
  • 但总是播放目录中的第一个音频。您要么只有一个音频文件,要么生成的随机数是恒定的。所以,检查onlyMP3s的内容。
  • 是的,你是对的。 onlyMP3s 是空的,所以我不明白为什么如果数组为空,我会实现播放文件。
  • dirContents 也是空的!

标签: ios objective-c nsfilemanager nsbundle on-demand-resources


【解决方案1】:

你没有忘记beginAccessingResourcesWithCompletionHandler:调用来实际下载资源吗?

- (IBAction)randomPlay {
    NSBundleResourceRequest *request1; // I hope you properly initialize this request :)
    [request1 beginAccessingResourcesWithCompletionHandler:^(NSError * _Nullable error) {
        if (error != nil) {
            // Probably, add here dispatch_async(dispatch_get_main_queue(), ^{
            NSString *bundleRoot = [[request1 bundle] bundlePath];
            NSFileManager *fm = [NSFileManager defaultManager];
            NSArray *dirContents = [fm contentsOfDirectoryAtPath:bundleRoot error:nil];
            NSPredicate *fltr = [NSPredicate predicateWithFormat:@"self ENDSWITH '.mp3'"];
            NSArray *onlyMP3s = [dirContents filteredArrayUsingPredicate:fltr];
            .
            .
            .
            [self playSelectedAudio:audio];
            // You will probably need to invoke [request1 endAccessingResources] later, when you finish accessing your audio.
        }
        else {
            // handle error
            [request1 endAccessingResources];
        }
    }
}

来自 NSBundle.h 的几个重要说明:

当资源可用或发生错误时,将在非主串行队列上调用完成块。

因此,您可能需要在完成处理程序的主队列中使用额外的dispatch_async。但这完全取决于您的代码。

确保始终调用 -endAccessingResources 方法来平衡对 begin 方法的调用,即使在完成处理程序中出现错误的情况下也是如此。

【讨论】:

  • 嘿!感谢您的回答!我已经在 viedDidLoad 中调用了它。我用代码更新了问题。
猜你喜欢
  • 2011-03-30
  • 2011-06-24
  • 1970-01-01
  • 2014-11-11
  • 2011-04-23
  • 2015-01-04
  • 1970-01-01
  • 2012-10-15
  • 1970-01-01
相关资源
最近更新 更多