UITableViewのスワイプ削除を実装する方法

Xcode

何気なく操作している左スワイプしてセルを削除するアクション。どのように実装されているか気になりませんか?

今回は、UITableViewのセルをスワイプして削除する方法を実装してみたいと思います。

私は、メモアプリを作成しているとき、セルを削除する方法がわからなくて、調べて実装しました。ある関数を追加することでセルをスワイプで削除できるようになります。

参考にしたサイトはこちらです。

【Swift5】UITableViewの編集モード、スワイプアクションについてまとめてみた|Blog(スワブロ) | スワローインキュベート
特許技術を活用した「ヒューマンセンシングSDKの開発」と「ソリューション提供」、「アプリ開発」などを事業としているスワローインキュベートの企業ブログです。最新の製品情報や、開発中の技術など、テクノロジー関連ブログのほか、スワローの社内行事や、社員によるブログ、求人情報なども公開しています。

注意が必要なのは、上記サイトは、画面表示上の削除だけの解説なっています。そのため、アプリを再起動すると削除したデータが復活します。私が作成していたメモアプリは、CoreDataというデータベースを使用しています。CoreDataにあるデータを削除しないと、再起動後、データが表示されてしまいます。なので、今回はCoreDataを使用してデータベース内のデータ管理をしてみたいと思います。

完成したら、このような動きになります。

プロジェクトを作成

最初は、プロジェクトを新規作成します。CoreDataはプロジェクトを作成するとき、項目にチェックを入れるとCoreDataに必要なファイルなどを追加することができます。

CoraDataを設定

CoraDataの設定をします。ENTITIESのところには、今回はEntityと名前を設定します。AttributesにTypeをStringのものを作成します。今回、名前はtestにします。

ストーリーボードを設定

ストーリーボードに、テーブルビューとボタンを配置していきます。テーブルビューのセルにIdentifierを設定します。今回は、例としてtestCellと入力します。

テーブルビューをViewController.swiftに接続します。接続するために、ViewController.swiftをエディタ上に表示します。下記の図の通りに操作してみてください。

「Assistant」をクリックするとViewController.swiftが表示されます。表示されたら、TableViewを選択してcontrolを押しながらドラッグします。そうすると、青い棒が表示されます。そうしたら、ViewController.swiftにドロップします。

ドロップをすると、下記のウィンドウが出てくるので、今回はNameのところに、testTableViewと入力します。

ボタンの設定をします。今回は、ボタンを押した時の動作について設定します。まずはボタンを選択してcontrolを押しながらドラッグします。そうしたら、ViewController.swiftにドロップします。

ドロップをすると、下記のウィンドウが出てくるので、今回はNameのところに、addTextと入力します。

コーディング

CoraDataのフレームワークを使用するために宣言します。

import CoreData

ViewController.swiftに変数を宣言します。

var textlist = [Entity]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

まずは、データを追加する関数を作成したいと思います。ボタンを押すとCoreDataにデータが追加され、セルにテキストが表示されます。

@IBAction func addText(_ sender: Any) {
        //空のデータを追加
        let newItem = Entity(context: self.context)
        //テキストを追加
        newItem.test = "test"
        textlist.append(newItem)
        //テーブルビューをリロード
        testTableView.reloadData()
    }

次にデータを読み込む関数を作成したいと思います。CoreDataのデータを読み込んで、データを宣言した配列に代入します。画面遷移先でCoreDataのデータを使用したい時は、必ずCoraDataの読み込みを忘れないようにしましょう。

func loadTextlist() {
        let request : NSFetchRequest = Entity.fetchRequest()
        do{
            textlist = try context.fetch(request)
        } catch {
            print("Error loading checklist \(error)")
        }
    }

次にデータ内容を保存する関数を作成したいと思います。追加したり、削除したデータをCoreDataにデータ内容を保存します。

func saveTextlist() { 
    do { 
        try context.save() 
      } catch { 
        print("Error saving Item \(error)") 
      } 
   }

UITableViewDataSourceUITableViewDelegateを継承させます。

extension ViewController: UITableViewDataSource, UITableViewDelegate {

}

上記のコード内にセルを表示させる関数を追加します。

extension ViewController: UITableViewDataSource, UITableViewDelegate {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return textlist.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "testCell", for: indexPath)
        
        cell.textLabel?.text = textlist[indexPath.row].test
        
        return cell
    }
}

次はUITableViewで、スワイプしてセルを削除する関数を実装します。この関数を追加すると、スワイプ削除のアクションを使用することができます。その関数の中に、CoreDataのデータを削除する処理を実装します。

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, 
forRowAt indexPath: IndexPath) { 
     let task = textlist[indexPath.row] 
     //データを削除 
     context.delete(task) 
     do { 
       textlist = try context.fetch(Entity.fetchRequest()) 
       } 
       catch{ 
         print("Error delete \(error)") 
          } 
          tableView.deleteRows(at: [indexPath], with: .automatic) 
          self.saveTextlist() 
  }

override func viewDidLoad()の中を下記のコードようにコーディングします。

override func viewDidLoad() {
        super.viewDidLoad()
        
        testTableView.delegate = self
        testTableView.dataSource = self
        self.loadTextlist()
        self.saveTextlist()
    }

全体のコードはこのような感じです。

import UIKit
import CoreData

class ViewController: UIViewController {
    
    @IBOutlet weak var testTableView: UITableView!
    var textlist = [Entity]()
    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        testTableView.delegate = self
        testTableView.dataSource = self
        self.loadTextlist()
        self.saveTextlist()
    }
    
    //MARK: - CoreData 読み込み
    func loadTextlist() {
        let request : NSFetchRequest = Entity.fetchRequest()
        do{
            textlist = try context.fetch(request)
        } catch {
            print("Error loading checklist \(error)")
        }
    }
    
    //MARK: - CoreData 保存する
    func saveTextlist() {
        do {
            try context.save()
        } catch {
            print("Error saving Item \(error)")
        }
    }
    
    //MARK: - セルにデータを追加
    @IBAction func addText(_ sender: Any) {
        //空のデータを追加
        let newItem = Entity(context: self.context)
        //テキストを追加
        newItem.test = "test"
        textlist.append(newItem)
        //テーブルビューをリロード
        testTableView.reloadData()
    }
}

extension ViewController: UITableViewDataSource, UITableViewDelegate {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return textlist.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "testCell", for: indexPath)
        
        cell.textLabel?.text = textlist[indexPath.row].test
        
        return cell
    }
    
    //MARK: - スワイプ削除の処理
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, 
forRowAt indexPath: IndexPath) {
        // 先にデータを削除しないと、エラーが発生する。
        let task = textlist[indexPath.row]
        //データを削除
        context.delete(task)
        do {
            textlist = try context.fetch(Entity.fetchRequest())
        }
        catch{
            print("Error delete \(error)")
        }
        tableView.deleteRows(at: [indexPath], with: .automatic)
        self.saveTextlist()
    }
    
}

以上でスワイプ削除して、CoraData内のデータも削除されるアプリが完成します。

タイトルとURLをコピーしました