NSBundleResourceRequest bundlePath

[问题最后更新]

我用我的应用程序播放一些audio文件。

我曾经在应用程序中存储文件,但后来我转移到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 { } }]; } }]; 

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

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

它工作正常。

所以在bundleRoot存在一个问题,就是不在我的文件所在的位置。

[UPDATE]

我其实是

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

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

你不忘记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方法的调用,即使在完成处理程序中出现错误的情况下也是如此。