Instantly share code, notes, and snippets.
Last active
September 3, 2021 10:40
-
Save imaizume/bd37a90ff35f74e7ccb6e50a02684cfd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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