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

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

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

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

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

Swift

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

Q&A

解決済

2回答

1884閲覧

TableViewのCellが2個表示されてしまう

hik_

総合スコア42

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

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

Swift

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

0グッド

0クリップ

投稿2019/03/17 10:15

編集2019/03/21 08:37

前提・実現したいこと

学習のためメモ帳アプリを作っていて、メモを作成して作成したメモをUserDefaultsで保存をする所まで作れたのですが、
メモを作成したCellをタップして文字を編集すると、編集後のテキストがあるCellだけで良いのですが、編集前のCellと編集後のCellの2つが作成されてしまう(例 「お菓子を買う」 というCellをタップして、TextViewに「お菓子を食べる」と書き直して保存を押すと、「お菓子を買う」だったCellが「お菓子を食べる」に変われば良いのですが、Cell1個目が「お菓子を買う」,Cell2個目に編集後の「お菓子を食べる」と2つ作成されてしまいます。)

イメージ説明

該当のソースコード

import UIKit // memoTextFieldに入力された文字を格納する変数 var memoText = [String]() class ViewController: UIViewController { // 変数を作成 var aDate: String = "" @IBOutlet weak var memoTextView: UITextView! override func viewDidLoad() { super.viewDidLoad() // memoTextViewにaDateを入れる memoTextView.text = aDate } @IBAction func setButton(_ sender: Any) { // memoTextにmemoTextViewに入力された文字を格納 memoText.append(memoTextView.text!) // memoTextをUserDefaultsに保存 UserDefaults.standard.set(memoText, forKey: "memoTextKey") } }
import UIKit class TableViewController: UITableViewController { // 変数 var honMemo: String = "" override func viewDidLoad() { super.viewDidLoad() if UserDefaults.standard.object(forKey: "memoTextKey") != nil { memoText = UserDefaults.standard.object(forKey: "memoTextKey") as! [String] } } override func viewDidAppear(_ animated: Bool) { // TableViewを開く度にtableViewを更新する tableView.reloadData() } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // memoTextの数だけCell作成 return memoText.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // Cellの表示内容を設定 let Cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) Cell.textLabel!.text = memoText[indexPath.row] return Cell } // Cellを押した時の処理 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { honMemo = memoText[indexPath.item] performSegue(withIdentifier: "Segue", sender: nil) } override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { // 削除機能 let index = indexPath.row memoText.remove(at: index) // 削除した事を保存 UserDefaults.standard.set(memoText, forKey: "memoTextKey") // tableViewを再読み込み tableView.reloadData() } // ViewControllerへの引き継ぎ設定 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { let vc = segue.destination as! ViewController vc.aDate = honMemo } }
import UIKit class TableViewCell: UITableViewCell { override func awakeFromNib() { super.awakeFromNib() // Initialization code } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) // Configure the view for the selected state } }

追記 3月21日

現状のコードです。
ご教示頂けると幸いです。

import UIKit // memoTextFieldに入力された文字を格納する変数 var memoText = [String]() // 再編集の場合の記事番号、-1なら新規作成 var honIndex = -1 var honRow: Int = honIndex class ViewController: UIViewController { // 変数を作成 var aDate: String = "" @IBOutlet weak var memoTextView: UITextView! override func viewDidLoad() { super.viewDidLoad() // memoTextViewにaDateを入れる memoTextView.text = aDate } @IBAction func setButton(_ sender: Any) { if honRow == honIndex { memoText.append(memoTextView.text!) } else { memoText[honRow] = memoTextView.text! } honRow = honIndex // memoTextにmemoTextViewに入力された文字を格納 memoText.append(memoTextView.text!) // memoTextをUserDefaultsに保存 UserDefaults.standard.set(memoText, forKey: "memoTextKey") } }
import UIKit class TableViewController: UITableViewController { // 変数 var honMemo: String = "" override func viewDidLoad() { super.viewDidLoad() if UserDefaults.standard.object(forKey: "memoTextKey") != nil { memoText = UserDefaults.standard.object(forKey: "memoTextKey") as! [String] } } override func viewDidAppear(_ animated: Bool) { // TableViewを開く度にtableViewを更新する tableView.reloadData() } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // memoTextの数だけCell作成 return memoText.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // Cellの表示内容を設定 let Cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) Cell.textLabel!.text = memoText[indexPath.row] return Cell } // Cellを押した時の処理 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { honMemo = memoText[indexPath.item] performSegue(withIdentifier: "Segue", sender: nil) } override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { // 削除機能 let index = indexPath.row memoText.remove(at: index) // 削除した事を保存 UserDefaults.standard.set(memoText, forKey: "memoTextKey") // tableViewを再読み込み tableView.reloadData() } // ViewControllerへの引き継ぎ設定 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { let vc = segue.destination as! ViewController vc.aDate = honMemo } }

試したこと

現在TableViewCellなど解決出来そうな情報を探しているのですが、実装出来ていない状況です。
ご教示頂けると幸いです。
よろしくお願いします。

補足情報(FW/ツールのバージョンなど)

Swift4 XCode10

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

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

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

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

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

guest

回答2

0

ベストアンサー

ViewController内のsetButtonでappendが2回呼ばれてしまっているので複数追加されてしまっています。
また、編集ができていないのはhonIndexに編集に使うための値を設定している箇所がないせいです。
didSelectRowAtでhonIndexの値を設定するようにしてやると想定通りの動きになると思います。
不明点等あればコメントください。
以下、コードです。

import UIKit class TableViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() if UserDefaults.standard.object(forKey: "memoTextKey") != nil { memoText = UserDefaults.standard.object(forKey: "memoTextKey") as! [String] } } override func viewDidAppear(_ animated: Bool) { // TableViewを開く度にtableViewを更新する tableView.reloadData() // 前画面から戻ってきたタイミングでhonIndexを初期化 honIndex = -1 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // memoTextの数だけCell作成 return memoText.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // Cellの表示内容を設定 let Cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) Cell.textLabel!.text = memoText[indexPath.row] return Cell } // Cellを押した時の処理 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // honIndexに押されたセル番号を格納 honIndex = indexPath.row performSegue(withIdentifier: "Segue", sender: nil) } override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { // 削除機能 let index = indexPath.row memoText.remove(at: index) // 削除した事を保存 UserDefaults.standard.set(memoText, forKey: "memoTextKey") // tableViewを再読み込み tableView.reloadData() } // ViewControllerへの引き継ぎ設定 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { let vc = segue.destination as! ViewController // 新規の時以外 if(honIndex != -1){ vc.aDate = memoText[honIndex] } } }
import UIKit // グローバルに持つのが良いのかどうかについては検討してください var memoText = [String]() // UserDefaultsに格納しているmemoTextKey var honIndex = -1 // 何番目のセルが押されたか class ViewController: UIViewController { // 編集のために前画面から値を受け取るための変数 var aDate: String = "" @IBOutlet weak var memoTextView: UITextView! override func viewDidLoad() { super.viewDidLoad() // 前画面からの編集用テキストを設定する memoTextView.text = aDate } @IBAction func setButton(_ sender: Any) { // -1のときは新規作成なので追加、それ以外のときはmemoTextを書き換える if honIndex == -1 { memoText.append(memoTextView.text!) } else { memoText[honIndex] = memoTextView.text! } // memoTextをUserDefaultsに保存 UserDefaults.standard.set(memoText, forKey: "memoTextKey") } }

投稿2019/03/21 10:57

razuma

総合スコア1313

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

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

hik_

2019/03/21 11:36 編集

ご回答ありがとうございます。ご回答通り実装してみた所無事解決出来ました。コードまで書いてくださり本当にありがとうございます。 現在iOSアプリをリリースすることを目標にSwift(プログラミング自体初めて)を勉強しているのですが、 この問題に既に1週間以上時間を使っていました。 やはり様々なことをプログラムで作っていくうちに、「〇〇の機能を実装したい」と思った時に、実装方法が浮かぶのでしょうか?自分はまだネットで調べて、しどろもどろしながら実装して、のトライアンドエラーなのですが、そうやって上達していくのでしょうか?何か上達のアドバイスがありました、教えてくださると嬉しいです。宜しくお願いします。
razuma

2019/03/21 12:12

おお、そうなんですね。もうちょっと早く気付いてあげられたら良かったです。 実装方法が思いつくかについてはある程度経験が必要になってくるかもしれません。 最初の頃は実装の仕方を考えるにしてもそもそもどう考えたら良いのか?と言う部分がわからないかもしれません。なのでこう言った詰まった部分の経験などを積み重ねていくと段々と理解できていくと思います。とは言え私も今でも実際に具体的な実装の仕方は検索して調べたり、具体的にしたいことが決まっていればそのサンプルを見ながら作ったりしてます。 あとは1行1行コードの意味を理解することや、何か思わぬことが起きたときも1行ずつ順を追ってみていくと問題が解決すると思います。 今回の例で言うと保存する部分がおかしいと思ったらsetButtonの中の処理をブレークポイントを張って1行ずつ見ていく。するとhonIndexには何が入ってきているのか、処理を通る中でmemoTextの値がどのように変わって最終的に何が保存されるのかが見えてくるので、どの値がどうなっていて欲しいのかがわかって修正するべき点が見えてくると思います。 いきなりはそう言ったことを実践したりするのも難しいと思いますので、少しづつ経験を積んで色々と覚えていけば良いのかなと思います。 アプリをリリースしたいと言う目標を持ってやっているのは素晴らしすぎると思いますので応援してます、がんばってくださいー。 私でお力になれそうな部分があれば回答させていただければと思ってますー。
hik_

2019/03/22 10:20

頑張りたいと思います。 丁寧にご返信頂きありがとうございました。
guest

0

おそらくですが、
①メモの新規追加
②既存メモの修正
のどちらも、ViewControllerクラスを使ってやっていると思いますが、

ViewControllerクラス側で①なのか②なのかの情報を持っておらず、ほぼ①の動作になっていることが原因だろうと思われます。

例えばViewController側で、

var aDate: String = ""

の他に

var honIndex = -1 // 再編集の場合の記事番号(-1なら新規作成)

などと定義しておき、既存メモの編集時にはデータのインデックスをここへ格納し、

@IBAction func setButton(_ sender: Any)の中で

honIndex == -1だったらmemoText.append(memoTextView.text!)
そうでなければmemoText[honIndex] = memoTextView.text!などとすれば期待する結果になると思われます。

細かい所は試行錯誤してください。

投稿2019/03/18 01:30

takabosoft

総合スコア8356

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

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

hik_

2019/03/18 02:23

ご回答ありがとうございます。試行錯誤してみます。
hik_

2019/03/21 08:34

試行錯誤してみたのですが、まだ解決には至ってない状況です。 色々試してみた現状のコードを質問内に追記しました。 アドバイスを頂けると幸いです。宜しくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問