【Xcode】Supporting Files内のファイルをdocumentsディレクトリにコピーする

この記事について

環境Xcode、Objective-C
目的Supporting Files内のファイルを初回起動時にdocumentsディレクトリにコピーする
結果AppDelegateのdidFinishLaunchingWithOptionsでNSFileManagerのcopyItemAtPathを実行する

つまずきポイント要約

  • パスがnullになったりコピーできない場合は、Copy Bundle Resourcesにファイルを追加しているか確認

Supporting Files内のファイルをdocumentsディレクトリにコピーしたときのスクリプト。
初回起動時に実行したかったので、スクリプトは、AppDelegate.m 内の didFinishLaunchingWithOptions: に記述した。

//didFinishLaunchingWithOptions は、アプリ起動時に呼び出される。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    

    //呼び出したいメソッドで下記を実行

    NSError *error;

    //NSFileManagerクラスは、Foundation フレームワーク(Cocoa Touchフレームワーク)にあるクラス。
    //Objective-C で、パスの存在を調べたり、ディレクトリを作成したりするのに使う。

    NSFileManager *fm = [NSFileManager defaultManager];

    
    //documentsディレクトリのパス

    NSArray  *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"コピーしたいファイル.jpg"];
                                NSLog(@"writableDBPath;%@",writableDBPath);



/*
    //常に新しいDBファイルにしたい場合は、アプリ起動時に必ずファイルを消去する。
    // pathのファイルを削除
    BOOL result = [fm removeItemAtPath:writableDBPath error:&error];
    if (result) {
        NSLog(@"ファイルを削除に成功:%@", writableDBPath);
    } else {
        NSLog(@"ファイルの削除に失敗:%@", error.description);
    }
*/

    
    BOOL result_flag = [fm fileExistsAtPath:writableDBPath];
    if(!result_flag){

        //dbが存在してなかったらここが呼ばれて、作成したDBをコピー

        //Supporting Files内に置いたファイルのパス
        //ここで null が帰ってきたりうまくコピーができなかったら、ファイルのコピーを許可していない可能性がある。許可の仕方はスクリプトのすぐ下に記述。

        NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"コピーしたいファイル.jpg"];


        //こっちの記述でもいい

        //NSString *defaultDBPath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"db"];

        
       //コピーを実行

        BOOL copy_result_flag = [fm copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
        if(!copy_result_flag){

            //失敗したらここ

            NSLog(@"コピーに失敗");
        }
    }

    

    return YES;
}

コピーするファイルは、あらかじめ許可しておく必要があるので、うまくコピーできない場合は許可されているか確認する。

targets > BuildPhase > Copy Bundle Resources
から適宜該当ファイルを追加すれば解消される。参考

//FMDB使っていて、データファイルをコピーしたときのスクリプトがこれ↓ 参考

    NSError *error;
    NSFileManager *fm = [NSFileManager defaultManager];
    
    NSArray  *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    
    NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"test.db"];
                                NSLog(@"writableDBPath;%@",writableDBPath);
    
    BOOL result_flag = [fm fileExistsAtPath:writableDBPath];
    if(!result_flag){
        //dbが存在してなかったらここが呼ばれて、作成したDBをコピー
        NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"test.db"];
        
        BOOL copy_result_flag = [fm copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
        if(!copy_result_flag){
            //失敗したらここ
            NSLog(@"データベースのコピーに失敗");
        }
    }
    
    //作成したテーブルからデータを取得
    FMDatabase* db = [FMDatabase databaseWithPath:writableDBPath];
    if ([db open]) {
        [db setShouldCacheStatements:YES];
        
        FMResultSet *rs = [db executeQuery:@"SELECT * FROM testdb"];
        while ([rs next]) {
            //ここでデータを展開
            NSLog(@"データ展開%d %@", [rs intForColumn:@"id"], [rs stringForColumn:@"title"]);
        }
        [rs close];  
        [db close];
    }else{
        //DBが開けなかったらここ
    }
タイトルとURLをコピーしました