Goalist Developers Blog

ファイルを出力してアプリ内に保存してみた@Swift3

こんちは。渡部です。

f:id:watabe1028:20170915114242p:plain

現在社内アプリを(勝手に)作っています。
そこでファイル出力させようとしたんですが
Objective-CではよくやってたんですがSwiftになってからは初めてだったんで
まとめてみました。
今回は任意のタイミングでテキストファイルやPDFファイルを作成する方法です。
アプリ内に保存した後、そのファイルの確認方法もついでに載せときます。
 

 

準備

まずは適当なプロジェクトのViewControllerに弊社サービスを牛耳る(三回目)ふろぐんのimageViewを貼り付けます。
ついでにUILabelも。
 
f:id:watabe1028:20170914150407p:plain

準備はこれだけです。
このあとはコーディングです。

 
 

文字列をテキストファイルに出力する方法

適当な文字列をテキストファイルに出力します。
今回は「HRogよろしくね!」という文字列を「sample.text」というファイルに出力します。

override func viewDidLoad() {
    super.viewDidLoad()
        
    self.createTextFromString(aString: "HRogよろしくね!", saveToDocumentsWithFileName: "sample.text")
}

// textファイルの出力
func createTextFromString(aString: String, saveToDocumentsWithFileName fileName: String) {
        
    if let documentDirectoryFileURL = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last {
            
        // 書き込むファイルのパス
        let targetTextFilePath = documentDirectoryFileURL + "/" + fileName
            
        do {
            try aString.write(toFile: targetTextFilePath, atomically: true, encoding: String.Encoding.utf8)
        } catch let error as NSError {
            print("failed to write: \(error)")
        }
    }
}

パスの指定はいくつか方法がありますが今回はStringで指定しています。
基本的にはStringかURLで指定するのが一般的だと思います。多分。
 
 

表示中の画面をPDFファイルに出力する方法

現在表示中の画面をPDFファイルに出力します。
「現在表示中の画面==self.view」ということにします。
ファイル名は「view.pdf」です。

override func viewDidLoad() {
    super.viewDidLoad()
                
    // textファイルの出力
    self.createTextFromString(aString: "HRogよろしくね!", saveToDocumentsWithFileName: "sample.text")

    // PDFファイルの出力
    self.createPdfFromView(aView: self.view, saveToDocumentsWithFileName: "view.pdf")
}

// pdfファイルの出力
func createPdfFromView(aView: UIView, saveToDocumentsWithFileName fileName: String) {
        
    let pdfData = NSMutableData()
    UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil)
    UIGraphicsBeginPDFPage()
        
    guard let pdfContext = UIGraphicsGetCurrentContext() else { return }
        
    aView.layer.render(in: pdfContext)
    UIGraphicsEndPDFContext()
        
    if let documentDirectories = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first {
        let documentsFileName = documentDirectories + "/" + fileName
        pdfData.write(toFile: documentsFileName, atomically: true)
    }
}

テキストファイルとは違い
・StringではなくData
・UIGraphicsBeginPDFContextToData
を使います。

基本的にソースをコピペすればそのまま使えるように書いてるので
詳細な説明は面倒なのでしません。

このソースで実行するとアプリ起動時にファイルを作成し、
アプリ内に保存されます。  
 

アプリ内に保存したファイルを確認する方法

先ほど保存したアプリ内のファイルをMacで取り出して確認します。
想定した通りに動けば「Documents」直下に「sample.text」と「view.pdf」が保存されてるはずです。
それでは確認手順です。
今回は実機で試した場合です。

iPhoneをMacに繋いだ状態で
Xcodeの「Window」「Devices」を選択します。

f:id:watabe1028:20170914154617p:plain

すると「Devices」ウィンドウが開くので
左ペインの「DEVICES」で自分のiPhoneを選択します。
「Installed Apps」から実行したアプリを選択し、
下の設定ボタンを押下。

f:id:watabe1028:20170914154642p:plain

「Download Container」で適当な場所にファイルをダウンロードします。

f:id:watabe1028:20170914153602p:plain

ダウンロードしたファイルを右クリックし、
「パッケージの内容を表示」を選択します。

f:id:watabe1028:20170914153637p:plain

するとアプリ内のファイル格納ディレクトリがあるので
「Documents」まで行くと、、、

f:id:watabe1028:20170914154034p:plain

テキストファイル、ちゃんとできてる!

f:id:watabe1028:20170914153725p:plain

PDFもできてる!

f:id:watabe1028:20170914153742p:plain

うぇい
 
 

ちなみにアプリ内にファイルを保存できるディレクトリは3つあります。
各ディレクトリに意味があるので注意が必要です。
もちろんリジェクト対象です。
 
Documents
・ユーザが作成したデータを保存する場所
・ユーザがアクセスできる
・ゆえに見せても構わないファイルのみにすること
・iTunesでバックアップされる

Library
・ユーザのデータファイル以外を保存する場所
・ユーザに見せたくないファイルを保存する
・ユーザデータのファイル保存には使ってはいけない
・iTunesでバックアップされる

temp
・一時ファイルを書き込むための場所
・次に起動するときには消えてる
・アプリが動作していないとき、システムが全て消去することがある
・iTunesでバックアップされない

 
 

まとめ

基本的にユーザのデータはUserDefaultsに保存してますが
たまにファイルに書き出して保存したい時があります。
そんなときにファイルどうやって書き出すんだっけ?というのを防ぐために
自分のためだけに書きました。
うぇい!