Swift

【Swift】UITableViewの編集モードで削除・並び替えをする

TableViewの編集モードで削除・並び替えをし、それを配列に反映する方法を解説します

ここでは配列を編集しますが、後の記事ではローカルのデータベースである「RealmSwift」にデータを保存する方法まで解説します

TableViewで編集モードを使う

「UITableView」に配列を表示させているところから始めますので「TableView」の使い方がわからない場合は下の記事をご覧ください

コードはこんな感じのところから始めます

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    @IBOutlet weak var tableView: UITableView!
    var languages: [String] = ["Swift", "Java", "Ruby", "Javascript", "PHP"]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.delegate = self
        tableView.dataSource = self
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return languages.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
        cell.textLabel?.text = languages[indexPath.row]
        return cell
    }
}

NavigationControllerを使う

まずは「ViewController」を「NavigationController」に入れます

セルの選択をできないようにするため、「TableView」の「Selection」を「No Selection」にします

コードを書く

全体のコードは最後に載せてあります

まず、「viewDidLoad()」に「NavigationController」のボタンを追加します

「editButtonItem」はもともとあるやつをつかいます

let addBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addButtonPressed(_ :)))
navigationItem.rightBarButtonItems = [editButtonItem, addBarButtonItem]

このままだとエラーになるので「追加ボタン(addButton)」が押された時の処理を追加します

ここでは入力されたアイテムが配列に追加されるようにします

追加されたら配列が出力されるようにします

@objc func addButtonPressed(_ sender: UIBarButtonItem) {
    var textField = UITextField()
    let alert = UIAlertController(title: "新しいアイテムを追加", message: "", preferredStyle: .alert)
    let action = UIAlertAction(title: "追加", style: .default) { (action) in
        self.languages.append(textField.text!)
        self.tableView.reloadData()
        print(self.languages)
    }
    alert.addTextField { (alertTextField) in
        alertTextField.placeholder = "アイテムを入力"
        textField = alertTextField
    }
        
    alert.addAction(action)
    present(alert, animated: true, completion: nil)
}

日本語の設定にする

この時点では編集ボタンが英語のままになっているので日本語になるようにします

英語のままでよければとばしても大丈夫です

まず、「Localization native development region」を「Japan」にします

次に「Japan」にしたところあたりで右クリックし、「Add Row」を選択します

「Localizations」を選択し、「Item0」を「Japanese」にします

編集モード

次に、編集ボタンを押したら編集モードを切り替える処理を書きます

override func setEditing(_ editing: Bool, animated: Bool) {
    super.setEditing(editing, animated: animated)
    tableView.setEditing(editing, animated: animated)
    tableView.isEditing = editing
}

削除の処理

アイテムが削除された時の処理を追加します

配列と「TableView」から削除します

削除されたら配列が出力されるようにします

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
        languages.remove(at: indexPath.row)
        tableView.deleteRows(at: [indexPath], with: .fade)
        print(languages)
    }
}

並び替えの処理

並び替えの処理を書きます

「fromIndexPath.row」はセルを動かす前の位置

「to.row」はセルを動かした後の位置です

動かす前のセルを保持し、削除してから動かした後の位置に挿入します

並び替えたら配列が出力されるようにします

//並び替え時の処理
func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
    let language = languages[fromIndexPath.row]
    languages.remove(at: fromIndexPath.row)
    languages.insert(language, at: to.row)
    print(languages)
}

//並び替えを可能にする
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
    return true
}

全体のコード

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    @IBOutlet weak var tableView: UITableView!
    var languages: [String] = ["Swift", "Java", "Ruby", "Javascript", "PHP"]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.delegate = self
        tableView.dataSource = self
        
        let addBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addButtonPressed(_ :)))
        navigationItem.rightBarButtonItems = [editButtonItem, addBarButtonItem]
    }
    
    @objc func addButtonPressed(_ sender: UIBarButtonItem) {
        var textField = UITextField()
        let alert = UIAlertController(title: "新しいアイテムを追加", message: "", preferredStyle: .alert)
        let action = UIAlertAction(title: "追加", style: .default) { (action) in
            self.languages.append(textField.text!)
            self.tableView.reloadData()
            print(self.languages)
        }
        alert.addTextField { (alertTextField) in
            alertTextField.placeholder = "アイテムを入力"
            textField = alertTextField
        }
        
        alert.addAction(action)
        present(alert, animated: true, completion: nil)
    }
    
    override func setEditing(_ editing: Bool, animated: Bool) {
        super.setEditing(editing, animated: animated)
        tableView.setEditing(editing, animated: animated)
        tableView.isEditing = editing
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return languages.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
        cell.textLabel?.text = languages[indexPath.row]
        return cell
    }
    
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            languages.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: .fade)
            print(languages)
        }
    }
    
    func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
        let language = languages[fromIndexPath.row]
        languages.remove(at: fromIndexPath.row)
        languages.insert(language, at: to.row)
        print(languages)
    }
    
    func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
        return true
    }
}

RealmSwiftにデータを保存する

これで、「TableView」の編集を配列に反映させることができましたが、このままではアプリを閉じるとデータが消えてしまうため、実用的ではありません

次回の記事では今回配列で削除や並び替えなどをしたデータをローカルなデータベースである「RealmSwift」を使って保存していく方法を解説していきます