-
I used:
func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration?
for swiping right and making an item or a cell a favorite. -
Added a
UISwtich
for toggling favorites items to be displayed only, otherwise display all items togehter: favorite and unfavorite. -
I make unfavorite items hidden when toggled on by making their cell’s height equal to 0. And restore their height when untoggled.
-
Few more things to consider (wasn’t part of the challenge but its a common sense and going that extra mile):
- When swiping right on the item it makes it favorite, and additional right swipe should make it unfavorite again.
- Adding new item when favorite toggle is on, should add a new favorite item. And when it isn’t toggled on, should add a regular/unfavorite item.
Happy to help if you have any questions. Happy coding.
Items.swift
import UIKit
class Item: Equatable {
static func == (lhs: Item, rhs: Item) -> Bool {
return lhs.name == rhs.name
&& lhs.serialNumber == rhs.serialNumber
&& lhs.valueInDollars == rhs.valueInDollars
&& lhs.dateCreated == rhs.dateCreated
}
var name: String
var valueInDollars: Int
var serialNumber: String?
let dateCreated: Date
var isFavorite = false
init(name: String, serialNumber: String?, valueInDollars: Int) {
self.name = name
self.valueInDollars = valueInDollars
self.serialNumber = serialNumber
self.dateCreated = Date()
}
convenience init (random: Bool = false){
if random {
let adjectives = ["Fluffy", "Rusty", "Shiny"]
let nouns = ["Bear", "Spork", "Mac"]
let randomAdjectives = adjectives.randomElement()!
let randomNoun = nouns.randomElement()!
let randomName = "\(randomAdjectives) \(randomNoun)"
let randomValue = Int.random(in: 0..<100)
let randomSerialNumber = UUID().uuidString.components(separatedBy: "-").first!
self.init(name: randomName,
serialNumber: randomSerialNumber,
valueInDollars: randomValue)
} else {
self.init(name: "", serialNumber: nil, valueInDollars: 0)
}
}
}
ItemsViewController.swift
import UIKit
class ItemsViewController: UITableViewController {
var itemsStore: ItemStore!
@IBOutlet var favoriteSwitch: UISwitch!
@IBAction func favoriteToggle(_ sender: UISwitch){
tableView.reloadData()
}
@IBAction func addNewItem(_ sender: UIButton) {
// Create a new item and add it to the store
let newItem = itemsStore.createItem()
// Figure out where the item is in the array
if let index = itemsStore.allItems.firstIndex(of: newItem){
let indexPath = IndexPath(row: index, section: 0)
if favoriteSwitch.isOn {
newItem.isFavorite = true
newItem.name += "⭐"
}
// Insert or remove this new row into the table
tableView.insertRows(at: [indexPath], with: .automatic)
}
}
@IBAction func toggleEditingMode(_ sender: UIButton){
// If you are currently in editing mode...
if isEditing {
// Change text of button to inform user of state
sender.setTitle("Edit", for: .normal)
// Turn off editing mode
setEditing(false, animated: true)
} else {
// Change text of button to inform user of state
sender.setTitle("Done", for: .normal)
// Enter editing mode
setEditing(true, animated: true)
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
itemsStore.allItems.count
}
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Get a new or recycled cell
let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath)
// Set the text on the cell with the description of item
// that is at the nth index of item, where n = row this cell
// will appear in on the table view
let item = itemsStore.allItems[indexPath.row]
cell.textLabel?.text = item.name
cell.detailTextLabel?.text = "$\(item.valueInDollars)"
return cell
}
override func tableView(_ tableView: UITableView,
commit editingStyle: UITableViewCell.EditingStyle,
forRowAt indexPath: IndexPath) {
// If the table view is asking to commit a delete command...
if editingStyle == .delete {
let item = itemsStore.allItems[indexPath.row]
// Remove the item from the store
itemsStore.removeItem(item)
// Also remove that roe from the table view with an animation
tableView.deleteRows(at: [indexPath], with: .automatic)
}
}
override func tableView(_ tableView: UITableView,
moveRowAt sourceIndexPath: IndexPath,
to destinationIndexPath: IndexPath) {
// Update the model
itemsStore.moveItem(from: sourceIndexPath.row, to: destinationIndexPath.row)
}
override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let action = UIContextualAction(style: .normal,
title: "⭐",
handler: { action, view, completion in
let item = self.itemsStore.allItems[indexPath.row]
switch item.isFavorite {
case true:
item.isFavorite = false
item.name = item.name.trimmingCharacters(in: ["⭐"])
case false:
item.isFavorite = true
item.name += "⭐"
}
self.tableView.reloadRows(at: [indexPath], with: .automatic)
} )
return UISwipeActionsConfiguration(actions: [action])
}
override func tableView(_ tableView: UITableView,
heightForRowAt indexPath: IndexPath) -> CGFloat {
if favoriteSwitch.isOn,
!itemsStore.allItems[indexPath.row].isFavorite {
return 0
}
return tableView.rowHeight
}
}