iOSアプリのファイル保存について


## はじめに

iOSアプリのファイル保存が可能なディレクトリは以下のようになっている(はず)

```
iOS App
	├── Documents
	├── Library
	│   ├── Caches
	│   └── Preferences
	└── tmp
```

また、保存するファイルによってどこに保存をするかをガイドラインに従ってわけなければリリース申請でリジェクトされてしまう

[iOS Data Storage Guidelines - Apple Developer](https://developer.apple.com/icloud/documentation/data-storage/index.html)

以下リンク引用

[ファイルシステムプログラミングガイド (TP40010672 0.0.0)](https://developer.apple.com/jp/documentation/FileSystemProgrammingGuide.pdf)

## Documents

> ユーザが作成したデータを保存するために使います。ファイル共有の機能により、ユーザはこのディレクトリ以下にアクセスできます。したがって、ユーザに見せても構わないファイルのみおいてください。
このディレクトリはiTunesによってバックアップされます。

## Library

> これは、ユーザのデータファイル以外のファイル用の最上位ディレクトリです。通常、標準的なサブディレクトリを用意し、いずれか適当な場所に保存します。iOSアプリケーションは通常、Application SupportおよびCachesというサブディレクトリを使いますが、独自のサブディレクトリを作成しても構いません。
ユーザに見せたくないファイルはLibraryサブディレクトリ以下に置いてください。ユーザデータのファイル保存用に使ってはなりません。
Libraryディレクトリの内容は、Cachesサブディレクトリ以下を除き、iTunesによるバックアップの対象になります。

### Application Support

> このディレクトリは、ユーザのドキュメントに関連付けられていないアプリケーションデータファイルを保存する場合に使用します。たとえば、アプリケーションで生成されたデータファイル、設定ファイル、テンプレート、その他のアプリケーションで管理される固定リソースまたは修正可能なリソースの保存にこのディレクトリを使用できます。アプリケーションも、アプリケーションのバンドルに元々格納されていたリソースの修正可能なコピーを保存する場合に、このディレクトリを使用する場合があります。ゲームでは、ユーザが購入した新しいレベル、またサーバからダウンロードされた新しいレベルの保存にこのディレクトリが使用されます。
このディレクトリのすべての内容は、アプリケーションのバンドルIDまたは社名を名前に使った、カスタムサブディレクトリに置かれます。
iOSでは、このディレクトリの内容はiTunesによってバックアップされます。

### Caches

> このディレクトリは、アプリケーションが簡単に作成し直すことが可能な、アプリケーション固有のサポートファイルの記述に使用します。一般的にアプリケーションはこのディレクトリの内容の管理、および必要に応じたファイルの追加と削除に責任を持ちます。iOS 2.2以降では、このディレクトリの内容がiTunesによってバックアップされません。また、iTunesはデバイスの完全な復元の間に、このディレクトリのファイルを削除します。
iOS 5.0以降では、まれですが、システムのディスクスペースが非常に少ない場合に、Cachesディレクトリが削除される場合があります。このような削除は、アプリケーションの実行中は起こりません。ただし、Cachesディレクトリが消去される状況は、iTunesの復元時に限らないことを覚えておいてください。

## tmp

> このディレクトリは、アプリケーションを次に起動するまで保持する必要のない一時ファイルを書き込むために使用します。不要になったファイルは削除しなければなりません。もっとも、アプリケーションが動作していないときに、システムがこのディレクトリ以下をすべて消去することがあります。
iTunesはこのディレクトリの内容をバックアップしません

## 各ディレクトリパスの取得

### Documents

```swift
let documentsPath = NSHomeDirectory() + "/Documents"
```

### Library

```swift
let libraryPath = NSHomeDirectory() + "/Library"
let applicationSupportPath = NSHomeDirectory() + "/Library/Application Support"
let cachesPath = NSHomeDirectory() + "/Library/Caches"
```

### tmp

```swift
let tmpDirectory = NSHomeDirectory() + "/tmp"
```

ぶっちゃけ簡単に書けばこうなるけどtypoが多そうなので `NSSearchPathForDirectoriesInDomains()` を使うとtypoがなくなるかな？

```swift
let path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
```

| ディレクトリ | 要素 |
| :-: | :-: |
| Documents | .DocumentDirectory |
| Library | .LibraryDirectory |
| Library/Application Support | .ApplicationSupportDirectory |
| Library/Caches | .CachesDirectory |

また、 `tmp` ディレクトリは `NSTemporaryDirectory()` を使うことでパスを取得可能

```swift
let path = NSTemporaryDirectory()
```

`NSSearchPathForDirectoriesInDomains()` と違って `/~/~/tmp/` のように文字列末に `/` が入ってくるので注意が必要。

例でDocumentsにファイルを音楽ファイルを保存してみる

```swift
let musicUrl = NSURL(string: "http://www.hurtrecord.com/se/operation/b1-007_computer_01.mp3")
if let url = musicUrl {
    let musicData = NSData(contentsOfURL: url)
    
    let dataName = "hoge.mp3"
    
    let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
    
    if let data = musicData {
        data.writeToFile("\(documentsPath)/\(dataName)", atomically: true)
    }
}
```

http://www.hurtrecord.com/se/operation/
著作権フリーBGMを使用させていただきました。