LoginSignup
0
0

More than 1 year has passed since last update.

CollectionViewを用いたToDoリストへの削除機能の実装

Last updated at Posted at 2023-02-15

概要

  • TableViewでは左スワイプでの削除機能が簡単に実装できるが(例:LINEのトーク削除)、CollectionViewだとそうはいかない

そこで、タスクを長押ししたら確認画面が出て”完了”にできる機能を実装する

コード

1. recognizerの作成とアタッチ

override func viewDidLoad() {
	super.viewDidLoad()

	//略

    let recognizer = UILongPressGestureRecognizer(target: self, action: #selector(deleteConfirm))
	collectionView.addGestureRecognizer(recognizer)

	//略

}

まずは、viewDidLoad内でrecognizerを作成する。recognizerとはタッチやスワイプを検知するためのもので、今回は長押しを検知するのでUILongPressGestureRecognizerを用いる。

actionには長押しした際に実行する処理を書くことができ、今回はdeleteConfirmというメソッドを実行させる。

また、作成したrecognizercollectionViewにアタッチ(取り付け)する。この時点ではまだdeleteConfirmというメソッドを作成していないのでエラーが出るが気にしなくて良い。

2. deleteConfirmメソッドの作成

class MemoCollectionViewController: UIViewController {

	//略

	override func viewDidLoad() {
    	super.viewDidLoad()

		//略

	}

    @objc func deleteConfirm(sender: UILongPressGestureRecognizer){
        
    	print("長押しされました")
        
    }

    //略

}

viewDidLoadの下あたり(class内であればどこでも問題ない)にdeleteConfirm メソッドを作成する。この際、先頭に@objc と書かないとエラーが起こるので注意。長押しされた際の処理はひとまずprint としておき、きちんと動作するか確認する。

シミュレータで実行してみると、長押ししたときに一回、押していた指を離したときに一回deleteConfirm メソッドが呼び出されているのがわかる。これはUILongPressGestureRecognizer の特徴であり、今回は一度目の呼び出しのみを用いたいので以下のコードをdeleteConfirm 内に付け足す。

@objc func deleteConfirm(sender: UILongPressGestureRecognizer){
        
	guard sender.state == .began else { return }
	print("長押しされました")
        
}

これによって、タスクが長押しされたときに一度だけdeleteConfirm メソッドが呼ばれるようになる。

3. 確認用アラートの作成と表示

@objc func deleteConfirm(sender: UILongPressGestureRecognizer){

	guard sender.state == .began else { return }
    print("長押しされました")

    let alert = UIAlertController(title: nil, message: "タスクを完了にしますか?", preferredStyle: .alert)    
	alert.addAction(
		UIAlertAction(title: "キャンセル", style: .cancel)
	)
	alert.addAction(
		UIAlertAction(title: "OK", style: .default)
	)
	present(alert, animated: true)
        
}

次に、確認用のアラートを作成する。ボタンはキャンセルボタンとOKボタンの2つを用意し、キャンセルボタンにはstyle: .cancel 、OKボタンにはstyle: .default を適用しておく。

4. indexPathの取得

@objc func deleteConfirm(sender: UILongPressGestureRecognizer){

	guard sender.state == .began else { return }
    print("長押しされました")

    let point: CGPoint = sender.location(in: collectionView)
    print(point)

    //略
        
}

まずは長押しされた位置のcollectionView 内の座標を取得する。CGPoint 型の変数にはX座標とY座標が入っている。

let point: CGPoint = sender.location(in: collectionView)
print(point)
let indexPath = self.collectionView.indexPathForItem(at: point)
print(indexPath)

次に、先ほど取得したタッチ位置を使って、セルのindexPath を取得する。indexPath の取得にはindexPathForItem メソッドを用いる。

タスクを長押しするとOptional([0, 0])Optional([0, 1]) のように、2つの数字の組み合わせが取得できていることを確認する。セルがないところを押すとnil になってしまうので、以下のコードを追加してindexPathnil のときは処理を終わらせるようにする。

let point: CGPoint = sender.location(in: collectionView)
print(point)
let indexPath = self.collectionView.indexPathForItem(at: point)
print(indexPath)
guard let indexPath else { return }

5. タスクを完了にする処理の実装

alert.addAction(
	UIAlertAction(title: "OK", style: .default, handler: {action in
    	self.titles.remove(at: indexPath.row)
        self.contents.remove(at: indexPath.row)
        self.collectionView.reloadData()
        self.saveData.set(self.titles, forKey: "titles")
        self.saveData.set(self.contents, forKey: "contents")
    })
)

最後に、OKボタンを押した際にタスクを”完了”にする処理を書く。具体的には、

  1. titlescontents から、該当するデータを削除する。
  2. collectionView をリロードする。
  3. userDefaults にデータを保存し直す。

といった手順でタスクを完了させる処理を書く。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0