Skip to content

Instantly share code, notes, and snippets.

@imaizume
Last active September 3, 2021 10:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save imaizume/bd37a90ff35f74e7ccb6e50a02684cfd to your computer and use it in GitHub Desktop.
Save imaizume/bd37a90ff35f74e7ccb6e50a02684cfd to your computer and use it in GitHub Desktop.
//
// ViewController.swift
//
// Created by @imaizume on 2021/09/03.
//
import UIKit
class ViewController: UIViewController {
private var list: [String] = ["Apple", "Banana", "Chocolate", "Donut"]
override func viewDidLoad() {
super.viewDidLoad()
// Initialize UITableView.
let tableView: UITableView = .init()
view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
view.leadingAnchor.constraint(equalTo: tableView.leadingAnchor, constant: 0),
view.trailingAnchor.constraint(equalTo: tableView.trailingAnchor, constant: 0),
view.topAnchor.constraint(equalTo: tableView.topAnchor, constant: 0),
view.bottomAnchor.constraint(equalTo: tableView.bottomAnchor, constant: 0)
])
// Set data source and delegate.
tableView.delegate = self
tableView.dataSource = self
// Set drag and drop delegate.
tableView.dragInteractionEnabled = true
tableView.dragDelegate = self
tableView.dropDelegate = self
}
}
extension ViewController: UITableViewDragDelegate {
func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
[.init(itemProvider: .init())]
}
}
extension ViewController: UITableViewDropDelegate {
func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?
) -> UITableViewDropProposal {
if session.localDragSession != nil {
return .init(operation: .move, intent: .insertAtDestinationIndexPath)
} else {
return .init(operation: .cancel, intent: .unspecified)
}
}
func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
guard let item = coordinator.items.first,
let destinationIndexPath = coordinator.destinationIndexPath,
let sourceIndexPath = item.sourceIndexPath else { return }
tableView.performBatchUpdates({ [weak self] in
guard let strongSelf = self else { return }
let element = strongSelf.list.remove(at: sourceIndexPath.row)
strongSelf.list.insert(element, at: destinationIndexPath.row)
tableView.deleteRows(at: [sourceIndexPath], with: .automatic)
tableView.insertRows(at: [destinationIndexPath], with: .automatic)
}, completion: nil)
coordinator.drop(item.dragItem, toRowAt: destinationIndexPath)
}
}
extension ViewController: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
true
}
}
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
true
}
func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
let configuration = UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { actions -> UIMenu? in
let copy: UIAction = .init(title: "Copy", image: UIImage(systemName: "doc.on.doc"), identifier: nil) { action in
if let cell = tableView.cellForRow(at: indexPath) {
UIPasteboard.general.string = cell.textLabel?.text
}
}
return .init(title: "Menu", image: nil, identifier: nil, children: [copy])
}
return configuration
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
list.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
guard indexPath.row < list.count else { return cell }
cell.textLabel?.text = list[indexPath.row]
return cell
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment