UICollectionViewCell 옮기기
UICollectionViewCell을 드래그 앤 드롭 방법으로 옮길 수 있는 방법은 두 가지가 있다.
ViewController가 UICollectionView를 상속받았을 경우와 그렇지 않은 경우 각각 다른 방법으로 가능하다.
UICollectionViewController 상속
import UIKit
class CollectionViewController: UICollectionViewController {
// MARK: - Properties
// MARK: Custom
var collectionData = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]
// MARK: - Methods
// MARK: View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
guard let layout = self.collectionViewLayout as? UICollectionViewFlowLayout else { return }
layout.itemSize = CGSize(width: ((self.view.bounds.width - 20) / 3), height: ((self.view.bounds.width - 20) / 3))
}
// MARK: Memory Management
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: UICollectionViewDataSource
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.collectionData.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
guard let textLabel = cell.viewWithTag(100) as? UILabel else { return UICollectionViewCell() }
textLabel.text = self.collectionData[indexPath.row]
return cell
}
// 이 메서드 내에 적절한 구현만 있다면 별도의 다른 코드는 추가하지 않아도 된다. (가장 편한 방법)
override func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let removed = self.collectionData.remove(at: sourceIndexPath.row)
self.collectionData.insert(removed, at: destinationIndexPath.row)
}
}
결과

UICollectionView 별도 구현
import UIKit
class ViewController: UIViewController {
// MARK: - Properties
// MARK: Custom
var collectionData = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]
// MARK: IBOutlet
@IBOutlet weak var mainCollectionView: UICollectionView!
// MARK: - Methods
// MARK: View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
guard let layout = mainCollectionView.collectionViewLayout as? UICollectionViewFlowLayout else { return }
layout.itemSize = CGSize(width: ((self.view.bounds.size.width - 20) / 3), height: ((self.view.bounds.size.width - 20) / 3))
// 1. Gesture 설정
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressGesture(_:)))
self.mainCollectionView.addGestureRecognizer(longPressGesture)
}
// MARK: Memory Management
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: Custom
// 2. Gesture 동작 설정
@objc func longPressGesture(_ gesture: UILongPressGestureRecognizer) {
switch gesture.state {
case .began:
guard let selectedIndexPath = mainCollectionView.indexPathForItem(at: gesture.location(in: mainCollectionView)) else { break }
self.mainCollectionView.beginInteractiveMovementForItem(at: selectedIndexPath)
case .changed:
self.mainCollectionView.updateInteractiveMovementTargetPosition(gesture.location(in: gesture.view!))
case .ended:
self.mainCollectionView.endInteractiveMovement()
default:
self.mainCollectionView.cancelInteractiveMovement()
}
}
}
// MARK: - Extension
// MARK: UI Collection View Data Source
extension ViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.collectionData.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
guard let textLabel = cell.viewWithTag(100) as? UILabel else { return UICollectionViewCell() }
textLabel.text = self.collectionData[indexPath.row]
return cell
}
}
// MARK: UI Collection View Delegate
extension ViewController: UICollectionViewDelegate {
// 3. 이동 가능하게 설정
func collectionView(_ collectionView: UICollectionView, canMoveItemAt indexPath: IndexPath) -> Bool {
return true
}
// 4. 내부 로직
func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let removed = self.collectionData.remove(at: sourceIndexPath.row)
self.collectionData.insert(removed, at: destinationIndexPath.row)
}
}
결과
