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

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

ただいまの
回答率

88.06%

Swift3 TableViewの文字がダブって表示されてしまいます。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 960

前提・実現したいこと

現在coradetaからデータを取り出しTableViewカスタムセルを使って2つのlabelを表示しています。
始め起動時には入力した文字或いは入力した文字がが入っているのですが2回目以降その一番初めに入力した文字まで再度TableViewに表示されてしまいます。

発生している問題・

TableViewの文字がダブって再度TableViewに表示されてしまいます。
2度、3度行うとnilが入ってしまう為エラーになってしまいます。

該当のソースコード

import UIKit
import CoreData

class ToDo_GoalViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
//MARK:プロパティ
    var todoTask:[String] = ["初めての投稿"]
    var goalTask:[String] = [""]
    var goalTaskDetail:[String] = [""]

    @IBOutlet weak var mainView: UIView!
    @IBOutlet weak var subView: UIView!
    @IBOutlet weak var TableView: UITableView!
    @IBOutlet weak var subTableView: UITableView!

    @IBAction func addToDo(_ sender: UIButton) {
        // テキストフィールド付きアラート表示
        let alert = UIAlertController(title: "ToDo", message: "文字を入力してください。", preferredStyle: .alert)
        // OKボタンの設定
        let okAction = UIAlertAction(title: "OK", style: .default, handler: {
            (action:UIAlertAction!) -> Void in
            // OKを押した時入力されていたテキストを表示
            if let textFields = alert.textFields {
                // アラートに含まれるすべてのテキストフィールドを調べる
                for textField in textFields {
                    //        AppDelegateのインスタンスを用意しておく
                    let appDelegate:AppDelegate = UIApplication.shared.delegate as! AppDelegate
                    //        エンティティを操作するためのオブジェクト
                    let viewContext = appDelegate.persistentContainer.viewContext
                    //        ToDoエンティティオブジェクトを作成
                    let ToDoGoal = NSEntityDescription.entity(forEntityName: "ToDoGoal", in: viewContext)
                    //        ToDoエンティティにレコード(行)を挿入するためのオブジェクトを作成
                    let newRecord = NSManagedObject(entity: ToDoGoal!, insertInto: viewContext)
                    //        追加したいデータ(txtTitleに入力された文字)のセット
                    if textField.text! == "" || textField.text! == nil{
                        print("nilが入っています。")
                    }else{
                        newRecord.setValue(textField.text!, forKey: "todoText")
//                        newRecord.setValue(Date(), forKey: "todoDeta")

                        //        レコード(行)の即時保存
                        do{
                            try viewContext.save()
                        }catch{
                        }
                        print("右の文字が入る\(textField.text!)")

                        self.todoTask.append(textField.text!)
                        self.TableView.reloadData()

                    }
                }
            }
        })
        alert.addAction(okAction)
        // キャンセルボタンの設定
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
        alert.addAction(cancelAction)
        // テキストフィールドを追加
        alert.addTextField(configurationHandler: {(textField: UITextField!) -> Void in
            textField.placeholder = "テキスト"
        })
        alert.view.setNeedsLayout() // シミュレータの種類によっては、これがないと警告が発生
        // アラートを画面に表示
        self.present(alert, animated: true, completion: nil)
    }


    //    ⑵行数を決める
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if tableView.tag == 1{
            print(tableView.tag)
            return todoTask.count
        }else{
            print(tableView.tag)
//            return goalTask.count
            return goalTaskDetail.count
        }
    }

    //    ⑶リストに表示する文字列を決定し、表示
    func tableView(_ tableView: UITableView, cellForRowAt indexPath:IndexPath) -> UITableViewCell {
        //        文字を表示するセルの取得(セルの再利用)
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomTableViewCell
        //        表示したい文字の設定
        if tableView.tag == 1{
            cell.textLabel?.text=todoTask[indexPath.row]
            return cell
        }else{
            cell.goalDetail?.text=goalTaskDetail[indexPath.row]
             cell.goalTitle?.text=goalTask[indexPath.row]
            return cell
        }
    }

     func read(){
        //        AooDelegateを使う用意をしておく
        let appDelegate:AppDelegate = UIApplication.shared.delegate as! AppDelegate
        //        エンティティを操作するためのオブジェクトを作成
        let viewContext = appDelegate.persistentContainer.viewContext
        //        どのエンティティからデータを取得してくるか設定
        let query:NSFetchRequest<ToDoGoal> = ToDoGoal.fetchRequest()
        do{
            //        データの一括取得
            let fetchResults = try viewContext.fetch(query)
            //        ループで一行ずつ表示
            for result : AnyObject in fetchResults {
                //                一行ずつのデータを取得する
//                MARK:todoTextのアペンド
                var todoText:String = ""
                if result.value(forKey: "todoText") == nil {
                    print("ToDoなし")
                }else{
                    todoText = result.value(forKey: "todoText") as! String
                    todoTask.append(todoText)
                    print("todoTextは:\(todoText)")
                }

//                MARK:goalTextのアペンド
                var goalText:String = ""
                var goaletail:String = ""//追加
                if result.value(forKey: "goalTitle") == nil || result.value(forKey: "goalDetail") == nil {
                    print("goalTextなし")
                     print("goalDetailなし")
                }else{
                    goalText = result.value(forKey: "goalTitle") as! String
                    goaletail = result.value(forKey: "goalDetail") as! String//追加
                    print("goalTitle:は\(goalText)")
                    print("goaletail:は\(goaletail)")//追加
                    goalTask.append(goalText)
                    goalTaskDetail.append(goaletail)//追加
                }
            }
        }catch{
            //            エラーが起きた時に通常処理の代わりに行う処理を記述(例外処理を記述する場合)
        }
    }

    override func viewWillAppear(_ animated: Bool) {
        // CoreDataからデータをfetchしてくる
        read()
        // self.TableView.reloadData()

         self.subTableView.reloadData()
    }


    //    MARK:初期設定メソッド
    override func viewDidLoad() {
        super.viewDidLoad()



        }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}
    @IBOutlet weak var textField: UITextField!

    @IBOutlet weak var textView: UITextView!



    @IBAction func addBtn(_ sender: UIButton) {

        let taskName = textField.text
        let task = textView.text
        //        let taskView = textView.text
        //        条件追加でから文字を指定できる
                    //            画面戻ります
            print("文字が入力された")
            let storyboard: UIStoryboard = self.storyboard!

            self.dismiss(animated: true, completion: nil)
            // context(データベースを扱うのに必要)を定義。
            let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
            // (データベースのエンティティです)型オブジェクトを代入します。
            let todogoal = ToDoGoal (context: context)
            // 先ほど定義したTask型データのname、categoryプロパティに入力、選択したデータを代入します。
        if taskName == "" || taskName == nil  || task == "" || task == nil {
            print("文字が入力されていない")
            //            textLabel.text = "文字が入力されていません"
        }else{

            todogoal.goalTitle = taskName!
            todogoal.goalDetail = task!

              print("タイトル:\(todogoal.goalTitle!)")
            print("詳細\(todogoal.goalDetail!)")


            // 上で作成したデータをデータベースに保存します。
            (UIApplication.shared.delegate as! AppDelegate).saveContext()
        }
    }


//    戻るボタン
    @IBAction func back(_ sender: UIButton) {
         self.dismiss(animated: true, completion: nil)
    }

    @IBAction func textFieldBack(_ sender: UITextField) {
    }

    func makeKeybord(){
        // 仮のサイズでツールバー生成
        let kbToolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: 320, height: 40))
        kbToolBar.barStyle = UIBarStyle.default  // スタイルを設定

        kbToolBar.sizeToFit()  // 画面幅に合わせてサイズを変更

        // スペーサー
        let spacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: self, action: nil)

        // 閉じるボタン
        let commitButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.done, target: self, action: #selector(GoalViewController.commitButtonTapped))

        kbToolBar.items = [spacer, commitButton]
        textView.inputAccessoryView = kbToolBar
    }

    func commitButtonTapped (){
        self.view.endEditing(true)
    }





    override func viewDidLoad() {
        super.viewDidLoad()
        makeKeybord()

    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()

    }


}

試したこと

tableViewのnumberOfRowsInSectionで表示行数の変更 ×
tableViewのcellForRowAt indexPathでreturnの文字変更 ×
func read()のアペンドしている箇所をprintで確認等
2~3回同じことを繰り返す(原因不明)

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

Swift3 Xcode10.3 Mac

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • KokokaraYoshiki

    2017/07/03 13:20

    TableViewの問題です。CoreDataのソースを削除いたしました。1回目の追加ボタンを押すと1回目の文字、2回目の追加ボタンを押すと1回目の文字と2回目の文字が表示されるといったように文字がダブってしまいます。これは一体なぜでしょか。

    キャンセル

  • fuzzball

    2017/07/03 13:34

    質問のコードではtodoTaskにしかデータが追加されていませんが、実際のコードでもgoalTaskにデータは追加されていない状態でしょうか?

    キャンセル

  • KokokaraYoshiki

    2017/07/03 14:42

    上記に再度記載させていただきました。

    キャンセル

回答 1

checkベストアンサー

0

セルが使い回されることを忘れないで下さい。

if tableView.tag == 1{
    cell.textLabel?.text = todoTask[indexPath.row]
    cell.goalDetail?.text = "" //※
    cell.goalTitle?.text = "" //※
    return cell
}else{
    cell.textLabel?.text = "" //※
    cell.goalDetail?.text = goalTaskDetail[indexPath.row]
    cell.goalTitle?.text = goalTask[indexPath.row]
    return cell
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/03 19:56

    ありがとうございました。
    解消されました。
    ご親切にありがとうございます。

    キャンセル

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

  • ただいまの回答率 88.06%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る