1

[質問の最後に更新]

アプリでいくつかのオーディオファイルを再生するために使用します。

以前はファイルをアプリに保存していましたが、その後 と に移動しまし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];
    }];

}

ほとんど機能していますが、常にディレクトリ内の最初のオーディオを再生しています。

4

1 に答える 1

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 メソッドの呼び出しのバランスを取るようにしてください。

于 2016-03-22T19:48:55.150 に答える