어떤 아이템을 오른쪽으로 스와이프하면 최애템이라는 표시가 뜨게 하기
보너스로는 버튼 등을 통해 최애템만 나타내게 하기
공식문서를 보니까 이 친구가 leading 에서 시작하는 스와이프를 인식해서 그에 따른 액션을 하는 메서드였다. 처음에는 그냥 스와이프 된 아이템의 isFavorite 프로퍼티를 true 로 바꿔주고 reloadRows(at:with) 메서드로 다시 로드 때렸다...
이렇게 하면 스와이프 시 최애템 설정이 되기는 하는데 정말 살짝만 스와이프를 해도 최애템으로 설정이 되어버렸다...왼쪽 스와이프 시 삭제되는 것과 비슷하게 하고 싶어서 메서드를 살펴봤더니 리턴값인 UISwipeActionsConfiguration 로 스와이프 시 액션을 지정할 수 있었다.
UISwipeActionsConfiguration 는 실제로 수행할 액션인 UIContextualAction 을 배열로 갖고 있으므로 UIContextualAction 를 내가 원하는 방식으로 설정해주면 될 것 같았다. 설정 방법은 솔직히 공식 문서만 보고서는 바로 이해가 안 가서 그냥 혼자 이것저것 뚝딱뚝딱 해보면서 깨달았다...
UIContextualAction(style:title:handler: UIContextualAction.Handler) 를 이용해서 생성했고, title 이랑 style 의 경우 초기화 시 바로 설정해줬고, 배경 색깔을 초기화 후 따로 background 프로퍼티를 통해 설정했다.
class ItemsViewController: UITableViewController {
...
override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let markAsFavorite = UIContextualAction(style: .normal, title: "Favorite?") { _, _, completionHandler in
let item = self.showOnlyFavaorites ? self.itemStore.favoriteItems[indexPath.row] : self.itemStore.allItems[indexPath.row]
item.isFavorite.toggle()
if self.showOnlyFavaorites {
tableView.reloadData()
} else {
tableView.reloadRows(at: [indexPath], with: .automatic)
}
completionHandler(true)
}
markAsFavorite.backgroundColor = .systemGreen
return UISwipeActionsConfiguration(actions: [markAsFavorite])
}
}
class ItemStore {
var favoriteItems: [Item] {
allItems.filter { $0.isFavorite }
}
}
class ItemsViewController: UITableViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
showOnlyFavaorites ? itemStore.favoriteItems.count : itemStore.allItems.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath)
let item = showOnlyFavaorites ? itemStore.favoriteItems[indexPath.row] : itemStore.allItems[indexPath.row]
cell.textLabel?.text = item.isFavorite ? "(favorite) \(item.name)": item.name
cell.detailTextLabel?.text = "$\(item.valueInDollars)"
return cell
}
private var showOnlyFavaorites = false
@IBAction func showOnlyFavorites(_ sender: UISwitch) {
showOnlyFavaorites.toggle()
tableView.reloadData()
}
}
class ItemsViewController: UITableViewController {
var itemStore: ItemStore!
@IBAction func addNewItem(_ sender: UIButton) {
let newItem = itemStore.createItem()
if let index = itemStore.allItems.firstIndex(of: newItem) {
let indexPath = IndexPath(row: index, section: 0)
// 모든 아이템을 보고 있을 때만 테이블에 추가
if !showOnlyFavaorites {
tableView.insertRows(at: [indexPath], with: .automatic)
}
}
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
let item = showOnlyFavaorites ? itemStore.favoriteItems[indexPath.row] : itemStore.allItems[indexPath.row]
itemStore.removeItem(item)
tableView.deleteRows(at: [indexPath], with: .automatic)
}
}
override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
if showOnlyFavaorites {
let fromItem = itemStore.favoriteItems[destinationIndexPath.row]
let toItem = itemStore.favoriteItems[sourceIndexPath.row]
let fromIndex = itemStore.allItems.firstIndex(of: fromItem)!
let toIndex = itemStore.allItems.firstIndex(of: toItem)!
itemStore.swapItemsAt(fromIndex, toIndex)
} else {
itemStore.moveItem(from: sourceIndexPath.row, to: destinationIndexPath.row)
}
}
}
class ItemStore {
func swapItemsAt(_ fromIndex: Int, _ toIndex: Int) {
if fromIndex == toIndex {
return
}
allItems.swapAt(fromIndex, toIndex)
}
}
class ItemsViewController: UITableViewController {
override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let markAsFavorite = UIContextualAction(style: .normal, title: "Favorite?") { _, _, completionHandler in
let item = self.showOnlyFavaorites ? self.itemStore.favoriteItems[indexPath.row] : self.itemStore.allItems[indexPath.row]
item.isFavorite.toggle()
if self.showOnlyFavaorites {
tableView.reloadData() // 바로 여기
} else {
tableView.reloadRows(at: [indexPath], with: .automatic)
}
completionHandler(true)
}
markAsFavorite.backgroundColor = .systemGreen
return UISwipeActionsConfiguration(actions: [markAsFavorite])
}
}