保存先と実行方法
入門の構造体とエラー処理を使います。空の練習フォルダーでmain.swiftを作り、swift main.swift で実行してください。例は実行時の作業フォルダーへファイルを作成・上書きします。各コードは独立しており、全体を置き換えて使えます。
Windowsでは 入門のコンパイル手順と同じく、main.swiftを書き換えるたびにコンパイルして実行します。
UTF-8で保存して読む
import Foundation でライブラリを使います。作業フォルダーからURLを作り、UTF-8で文字列を保存します。atomically: true は一時ファイルを利用して置き換える指定です。
import Foundation
let directory = URL(fileURLWithPath: FileManager.default.currentDirectoryPath)
let url = directory.appendingPathComponent("swift-memo.txt")
do {
try "Swiftの学習メモ".write(to: url, atomically: true, encoding: .utf8)
let text = try String(contentsOf: url, encoding: .utf8)
print(text)
} catch {
print("保存または読み込みに失敗しました")
}Swiftの学習メモ同じ場所にswift-memo.txtができ、その中に表示と同じ文字列があることも確認してください。書き込み権限がない場所ではcatchへ進みます。
CodableでJSONを往復する
Codable に適合する構造体はJSONEncoderでData(バイト列)へ変換し、JSONDecoderで元の型に戻せます。型がJSONの構造と一致しないとデコードは失敗します。
import Foundation
struct Memo: Codable {
let title: String
let minutes: Int
}
let directory = URL(fileURLWithPath: FileManager.default.currentDirectoryPath)
let url = directory.appendingPathComponent("swift-memo.json")
do {
let original = Memo(title: "Optional", minutes: 20)
let data = try JSONEncoder().encode(original)
try data.write(to: url, options: .atomic)
let saved = try Data(contentsOf: url)
let memo = try JSONDecoder().decode(Memo.self, from: saved)
print(memo.title)
print(memo.minutes)
} catch {
print("JSONを保存・読み込みできませんでした")
}Optional
20作成されるJSONは {"title":"Optional","minutes":20} と同じ内容です。キーの並び順はこの例では固定していません。Memo.self は変換先の型自体を渡す書き方です。
壊れたデータを読む場合
実際に不正なJSONを渡し、アプリを停止させずに失敗を伝えられるか確認します。存在しないファイル、型の違う値、必須キーがない場合も成功扱いにしないことが大切です。
import Foundation
struct Memo: Decodable { let minutes: Int }
let data = Data("{\"minutes\":\"二十\"}".utf8)
do {
let memo = try JSONDecoder().decode(Memo.self, from: data)
print(memo.minutes)
} catch {
print("minutesには整数が必要です")
}minutesには整数が必要です練習:複数のメモを保存
Memoの配列をswift-memos.jsonへ保存して読み戻し、合計学習時間を表示してください。10分と20分の2件なら30です。
解答例と結果を確認する
まず自分で書いてから、処理の順番と結果を比べましょう。
import Foundation
struct Memo: Codable { let minutes: Int }
let directory = URL(fileURLWithPath: FileManager.default.currentDirectoryPath)
let url = directory.appendingPathComponent("swift-memos.json")
do {
let memos = [Memo(minutes: 10), Memo(minutes: 20)]
try JSONEncoder().encode(memos).write(to: url, options: .atomic)
let data = try Data(contentsOf: url)
let restored = try JSONDecoder().decode([Memo].self, from: data)
var total = 0
for memo in restored { total += memo.minutes }
print(total)
} catch {
print("メモを保存・読み込みできませんでした")
}30公式ドキュメントで確認する:Foundation