Skip to content

Instantly share code, notes, and snippets.

@drewag
Created August 31, 2019 19:59
Show Gist options
  • Save drewag/f6bc7582637aad18274ba80d47820115 to your computer and use it in GitHub Desktop.
Save drewag/f6bc7582637aad18274ba80d47820115 to your computer and use it in GitHub Desktop.
Playground to Illustrate a Likable Table Cell
import UIKit
import PlaygroundSupport
// -----------------------------------------------------
// Model
//
// Types having to do with the storing and processing of
// data should be a part of the "Model" layer.
// -----------------------------------------------------
struct Post {
let text: String
var isLiked: Bool
}
// -----------------------------------------------------
// View
//
// Types having to do with displaying to the user and
// recieving their interactions should be a part of the
// "View" layer.
// -----------------------------------------------------
class PostCell: UITableViewCell {
let toggleLike = UIButton()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: .subtitle, reuseIdentifier: reuseIdentifier)
// Set up a bare bones cell programatically
self.toggleLike.setTitle("👍 Like", for: .normal)
self.toggleLike.setTitleColor(UIColor.black, for: .normal)
self.toggleLike.sizeToFit()
// Must put toggleLike in container view because the default
// table view logic overwrites the alpha of the accessory view
let accessory = UIView(frame: self.toggleLike.bounds)
accessory.addSubview(self.toggleLike)
self.accessoryView = accessory
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func prepareForReuse() {
super.prepareForReuse()
// Reset attributes that may be set when the cell is used. They will
// be set back to the correct values in tableView(:cellForRowAt:)
// Reset the alpha to 1 by default
self.toggleLike.alpha = 1
// Reset the text to being empty
self.textLabel?.text = ""
// Remove all of the actions from the toggleLike button
self.toggleLike.removeTarget(self.toggleLike.allTargets, action: nil, for: .allEvents)
}
}
// -----------------------------------------------------
// Controller
//
// The "Controller" is a thin layer to communicate between
// the View and the Model
// -----------------------------------------------------
class MyViewController: UITableViewController {
// Static data for this example
var posts: [Post] = (1 ... 50).map({ index in
return Post(text: "Post \(index)", isLiked: false)
})
override func viewDidLoad() {
super.viewDidLoad()
// Register that the PostCell class should be used when dequeing a cell for "PostCellIdentifier"
self.tableView.register(PostCell.self, forCellReuseIdentifier: "PostCellIdentifier")
}
@IBAction func toggleLike(sender: UIButton) {
// First, toggle the isLiked state on the model
self.posts[sender.tag].isLiked = !self.posts[sender.tag].isLiked
// Now animate the alpha change
UIView.animate(withDuration: 0.3) {
if self.posts[sender.tag].isLiked {
sender.alpha = 0.5
}
else {
sender.alpha = 1
}
}
}
}
// UITableViewControllerDataSource
//
/// It is often a good idea to separate responsbilities, even within
/// a single class u sing extensions
extension MyViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Now that we registerd PostCell as the cell for "PostCellIdentifier", we can retrieve an instance by dequeing it
let cell = tableView.dequeueReusableCell(withIdentifier: "PostCellIdentifier", for: indexPath) as! PostCell
// Get the post this cell is representing
let post = self.posts[indexPath.row]
// Configure the display
cell.textLabel?.text = post.text
if post.isLiked {
cell.toggleLike.alpha = 0.5
}
else {
cell.toggleLike.alpha = 1
}
// Set the tag on the toggle button so that we know which post to toggle
cell.toggleLike.tag = indexPath.row
// Set the toggleLike button to call "toggleLike" action on touch up inside
cell.toggleLike.addTarget(self, action: #selector(toggleLike), for: .touchUpInside)
return cell
}
}
PlaygroundPage.current.liveView = MyViewController()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment