プログラミングノート

一からものを作ることが好きなエンジニアの開発ブログです。

アプリケーションディレクトリの構造とアクセス方法

iOSではデータの保存場所として特定のディレクトリを利用することができます。


Best Albumではサムネイル画像、オリジナル画像を全てキャッシュディレクトリに保存しているのですが、パフォーマンス的に全く問題がなく、今後活用する機会も増えそうなのでまとめておきます。

ディレクトリ構造

  • /Documents

アプリ固有のデータファイルを保存するディレクトリ (バックアップされる)

  • /Library/Preferences

アプリ固有の環境設定ファイルを保存するディレクトリ (バックアップされる)
NSUserDefaults or CFPreferencesAPI経由で読み書きする

  • /Library/Caches

アプリ固有のサポートファイルを保存するディレクトリ (バックアップされない)

  • /tmp

一時ファイルを保存するディレクトリ (バックアップされない)

パスの取得

上記ディレクトリのうち、Preferencesは直接アクセスしてはだめで、tmp配下においても自動でクリーンアップされないため、実際に利用するのはDocumentsとCachesの2つで十分かと思います。それぞれのパス取得は下記の通りです。


/Documents

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *dir = [paths objectAtIndex:0];
NSLog(@"%@", dir);


/Library/Caches

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *dir = [paths objectAtIndex:0];
NSLog(@"%@", dir);

パスの連結

専用のメソッドが準備されています。

NSString *dirA = [dir stringByAppendingPathComponent:@"dirA"];
NSString *pathA = [dirA stringByAppendingPathComponent:@"image.png"];
NSLog(@"%@", pathA);

NSString *dirB = [dir stringByAppendingPathComponent:@"dirB"];
NSString *pathB = [dirB stringByAppendingPathComponent:@"image.png"];
NSLog(@"%@", pathB);

ディレクトリの操作

FileManager経由で操作できます。

NSFileManager *fm = [NSFileManager defaultManager];
NSError *error;

// チェック
[fm fileExistsAtPath:dirA];

// 作成
[fm createDirectoryAtPath:dirA withIntermediateDirectories:YES attributes:nil error:&error];

// 移動
[fm moveItemAtPath:dirA toPath:dirB error:&error];

// コピー
[fm copyItemAtPath:dirA toPath:dirB error:&error];

// 削除
[fm removeItemAtPath:dirA error:&error];

ファイルの操作

ファイルも同じく。

// 作成
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://xxx/xxx.png"]];
[fm createFileAtPath:pathA contents:data attributes:nil];

// 削除
[fm removeItemAtPath:pathA error:&error];

// 移動
[fm moveItemAtPath:pathA toPath:pathB error:&error];

// コピー
[fm copyItemAtPath:pathA toPath:pathB error:&error];

ファイルサイズの取得

今どれくらいキャッシュで利用しているかチェックしたい場合はこのような感じでチェック可能です。Cachesディレクトリ配下のサイズがbyteで返ってきます。

- (unsigned long long int)countCacheSize{
  unsigned long long int cacheSize = 0;

  NSFileManager *fm = [NSFileManager defaultManager];
  NSError *error;
  
  NSArray *cachePaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
  NSString *cacheDirectory = [cachePaths objectAtIndex:0];
  NSArray *cacheFileList = [fm subpathsAtPath:cacheDirectory];
  NSEnumerator *cacheEnumerator = [cacheFileList objectEnumerator];

  NSString *cacheFilePath;
  while (cacheFilePath = [cacheEnumerator nextObject]) {
    NSString *path = [cacheDirectory stringByAppendingPathComponent:cacheFilePath];
    NSDictionary *cacheFileAttributes = [fm attributesOfItemAtPath:path error:&error];
    cacheSize += [cacheFileAttributes fileSize];
  }
  NSLog(@"%llu", cacheSize);
  return cacheSize;
}