質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

3069閲覧

テーブルのデータをファイル出力したい

15DB109_hotaka

総合スコア22

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

1クリップ

投稿2018/01/05 01:35

現段階で色々試して、テーブルのデータを、ファイルを作成して
そこに保存することはできるようになりました。
しかし、1行目のデータだけや、指定した行目のデータしかファイルに保存さてていなく
実質、1行しかファイルに保存できていません。
今回教えていただきたいのは、テーブルの全行のデータをファイルに出力する方法です。
for文でループ処理も試みましたが、最後の行だけが出力され、またもや1行だけしか保存されませんでした。
処理として[SaveButtom]をタップしデータを作成したファイル(.csv)に保存します。
よろしくお願いします。
開発環境:Xcode8 Swift3

@IBAction func SaveButtom(_ sender: Any) { let name = self.name.text ?? "unknown" let thePath = NSHomeDirectory()+"/Documents/(name).csv" let count = toDoItems?.count ?? 0; for i in 0..<count { let textData = toDoItems?[i].name.description do { try textData?.write(toFile: thePath, atomically: true, encoding: String.Encoding.shiftJIS) } catch let error as NSError { print("保存に失敗。\n (error)") } } // let textData = toDoItems?[0].name.description // // do { // try textData?.write(toFile: thePath, atomically: true, encoding: String.Encoding.shiftJIS) // } catch let error as NSError { // print("保存に失敗。\n (error)") // } // ① UIAlertControllerクラスのインスタンスを生成 // タイトル, メッセージ, Alertのスタイルを指定する // 第3引数のpreferredStyleでアラートの表示スタイルを指定する let alert: UIAlertController = UIAlertController(title: "作成スコアを保存", message: "保存したデータは”データを送信する”からPCへ送信できます。", preferredStyle: UIAlertControllerStyle.alert) // ② Actionの設定 // Action初期化時にタイトル, スタイル, 押された時に実行されるハンドラを指定する // 第3引数のUIAlertActionStyleでボタンのスタイルを指定する // OKボタン let defaultAction: UIAlertAction = UIAlertAction(title: "保存", style: UIAlertActionStyle.default, handler:{ // ボタンが押された時の処理を書く(クロージャ実装) (action: UIAlertAction!) -> Void in print("保存") }) // キャンセルボタン let cancelAction: UIAlertAction = UIAlertAction(title: "保存しない", style: UIAlertActionStyle.cancel, handler:{ // ボタンが押された時の処理を書く(クロージャ実装) (action: UIAlertAction!) -> Void in print("保存しない") }) // ③ UIAlertControllerにActionを追加 alert.addAction(cancelAction) alert.addAction(defaultAction) // ④ Alertを表示 present(alert, animated: true, completion: nil) } @IBAction func addToDo(_ sender: Any) { if isValidateInputContents() == false{ return } // ToDoデータを作成する処理 let toDo = ToDo() toDo.name = todoNameText.text! // ToDoデータを永続化する処理 do{ let realm = try Realm() try realm.write{ realm.add(toDo) } todoNameText.text = "" }catch{ print("失敗") } tableView.reloadData() } private func isValidateInputContents() -> Bool{ // ToDo名のデータ入力 if let name = todoNameText.text{ if name.characters.count == 0{ return false } }else{ return false } return true } } extension ViewController: UITableViewDataSource{ func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return toDoItems?.count ?? 0 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let toDo = toDoItems?[indexPath.row] let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! ToDoTableViewCell // Realmに登録したデータをラベルに値設定 cell.nameLabel.text = toDo?.name print(toDo?.name) return cell } // 削除処理 func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == UITableViewCellEditingStyle.delete { let realm = try!Realm() _ = try!Realm().objects(ToDo.self) // これはRealmSwiftでデータを削除しているケース let deleteHistory = self.toDoItems?[indexPath.row] // トランザクションを開始してオブジェクトを削除します try! realm.write { realm.delete(deleteHistory!) } // TableViewを再読み込み. self.tableView.reloadData() } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ご提示の処理だと、1行ごとに同じファイルに上書き保存していることになります。
結果的に最後の行だけが保存されます。

保存すべきデータを用意したあと、そのデータを保存するようにしてください。

まず、保存するデータを用意します。

swift

1// ガード条件を用意して、エラー時には早期リターンした方が良い。 2// また、オプショナルは早期に、かつ安全にアンラップする。 3guard let items = toDoItems else { 4 print("データがない") 5 return 6} 7 8// 各name.descriptionプロパティを改行で連結 9let descriptions = items.map { $0.name.description }.joined(separator: "\n")

ついで、これを保存します。

swift

1do { 2 // do {} の中には try がない文も書いていい 3 // 上の保存データの生成は、まとまりとしてはここに書いた方が読みやすい 4 let descriptions = items.map { $0.name.description }.joined(separator: "\n") 5 6 // 文脈的に解釈可能であれば String.Encoding.shiftJIS は .shiftJIS に省略可能。 7 // 8 // 本当に shift JIS で保存する必要がありますか?  9 // ほとんどの場合 UTF8 の方が安全です。 10 try descriptions.write(toFile: thePath, atomically: true, encoding: .shiftJIS) 11 12} catch { // わざわざ NSError に変換する必要はない。また、記述がなければ Error は変数 error に自動的に代入される。 13 print("保存に失敗。\n (error)") 14}

あと、この質問とは関係ないですが、実際の保存はユーザーが保存を選んだ後に行った方が良いでしょう。
無駄な処理が減ります。

さらに、保存に時間がかかるようなら、保存は別スレッドで行う方が良いでしょう。
ユーザビリティが向上します。

投稿2018/01/05 02:19

編集2018/01/05 02:23
MasakiHori

総合スコア3384

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

15DB109_hotaka

2018/01/05 10:41

ありがとうございます! JISにしているのは、作成したファイルは最終的にエクセルで表示するためUTF8では文字化けしてしまいました。説明不足申し訳ないです。 今回ご教授いただいた記述は、この場所に該当しますか? let count = toDoItems?.count ?? 0; for i in 0..<count { let textData = toDoItems?[i].name.description do { try textData?.write(toFile: thePath, atomically: true, encoding: String.Encoding.shiftJIS) } catch let error as NSError { print("保存に失敗。\n (error)") } }
MasakiHori

2018/01/06 02:40

なぜ試してみないのですか?
15DB109_hotaka

2018/01/06 18:06

すいません、試した結果、無事成功しました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問