概要
- 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
というメソッドを実行させる。
また、作成したrecognizer
はcollectionView
にアタッチ(取り付け)する。この時点ではまだ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
になってしまうので、以下のコードを追加してindexPath
がnil
のときは処理を終わらせるようにする。
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ボタンを押した際にタスクを”完了”にする処理を書く。具体的には、
-
titles
とcontents
から、該当するデータを削除する。 -
collectionView
をリロードする。 -
userDefaults
にデータを保存し直す。
といった手順でタスクを完了させる処理を書く。