UITableViewのスワイプメニューを出したまま回転させるとリサイズされない

セルの左端が埋もれてしまう。横向きから縦向きにした時も同じ。

メニューを出したままで正しくリサイズさせるのが難しいので、セルを改造して回転時にメニューを閉じるようにします。

UITableViewDelegateでメニューを実装する

普通にスワイプメニューを出せるようにデリゲートを実装します。たまたま手元にあったサンプルを使っていますが、UITableViewControllerでも同じです。

class MyViewController: UIViewController, UITableViewDelegate {
    
    func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        let deleteAction = UIContextualAction(style: .destructive, title: NSLocalizedString("Delete", comment: "")) { action, view, completion in
            // 削除
            completion(true)
        }
        let editAction = UIContextualAction(style: .normal, title: NSLocalizedString("Edit", comment: "")) { action, view, completion in
            // 編集
            completion(true)
        }
        let config = UISwipeActionsConfiguration(actions: [deleteAction, editAction])
        config.performsFirstActionWithFullSwipe = false
        return config
    }
    
    func tableView(_ tableView: UITableView, willBeginEditingRowAt indexPath: IndexPath) {
        // メニューを開く時
    }
    
    func tableView(_ tableView: UITableView, didEndEditingRowAt indexPath: IndexPath?) {
        // メニューを閉じた時、自動的に閉じられた時
    }
}

セルをカスタマイズして対応する

レイアウト時にx座標がマイナスになった時に編集モードを抜けるようにします。抜ける時はセルではなくテーブルのisEditingを操作します。

class MyTableViewCell: UITableViewCell {
    
    private func closeSwipeActionsOnRotating() {
        if isEditing && frame.origin.x < 0 {
            (superview as? UITableView)?.isEditing = false
            frame.origin.x = 0
        }
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        closeSwipeActionsOnRotating()
    }
}

Xcode 10.2.1, iOS 12

この問題はiOS 13で修正されました

iOS 13ではMac対応の美しいコンテキストメニューが導入されました。スワイプメニューは便利ですが、CollectionViewのグリッド表示では使えなかったですし、今後は廃れていくかもしれませんね。