Skip to content

Instantly share code, notes, and snippets.

@ryangibson
Created February 19, 2017 22:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryangibson/4ecdbde6789022cc0db578a246c3b184 to your computer and use it in GitHub Desktop.
Save ryangibson/4ecdbde6789022cc0db578a246c3b184 to your computer and use it in GitHub Desktop.
import UIKit
import PlaygroundSupport
let cellIdentifier = "cellId"
let dataUrl = URL(string: "https://raw.githubusercontent.com/facebook/react-native/master/docs/MoviesExample.json")!
func contstraint(_ attr: NSLayoutAttribute, from: UIView, to: UIView) -> NSLayoutConstraint {
return NSLayoutConstraint(
item: from,
attribute: attr,
relatedBy: .equal,
toItem: to,
attribute: attr,
multiplier: 1,
constant: 1
)
}
struct Movie {
let title: String
let thumbnail: URL
init?(json: [String : Any]) {
guard let title = json["title"] as? String,
let images = json["posters"] as? [String : String],
let tumbnailURLString = images["thumbnail"],
let thumbnailURL = URL(string: tumbnailURLString)
else {
return nil
}
self.title = title
self.thumbnail = thumbnailURL
}
}
func loadMovies(completionHandler: @escaping ([Movie]) -> Void) {
let task = URLSession(configuration: .default).dataTask(with: dataUrl) { (data, response, error) in
if let data = data {
do {
if let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String : Any],
let movies = json["movies"] as? [[String : Any]]
{
completionHandler(movies.flatMap { Movie(json: $0) })
}
} catch {}
}
}
task.resume()
}
extension UIImageView {
func loadImage(url: URL, placeholder: String) {
image = UIImage(named: placeholder)
_ = URLSession(configuration: .default).dataTask(with: url) { [weak self] (data, response, error) in
if let data = data, let img = UIImage(data: data) {
DispatchQueue.main.async {
self?.image = img
}
} else if let err = error {
print("Error: \(url) \(err)")
} else {
print("Error: \(url)")
}
}.resume()
}
}
class MovieCell: UITableViewCell {
init() {
super.init(style: .default, reuseIdentifier: cellIdentifier)
}
required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
class MoviesListViewController: UITableViewController {
var data: [Movie]
init(movies: [Movie]) {
data = movies
super.init(style: .plain)
}
required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = makeCell(tableView)
cell.textLabel?.text = data[indexPath.row].title
cell.imageView?.loadImage(url: data[indexPath.row].thumbnail, placeholder: "placeholder")
return cell
}
func makeCell(_ tableView: UITableView) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) else {
return MovieCell()
}
return cell
}
}
class LoadingView: UIView {
var loadingLabel: UILabel = {
let label = UILabel()
label.text = "Loading..."
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.white
addSubview(loadingLabel)
addConstraints([
contstraint(.centerX, from: loadingLabel, to: self),
contstraint(.centerY, from: loadingLabel, to: self),
])
}
required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
}
class RootViewController: UIViewController {
var movieListVC: MoviesListViewController! = nil
override func viewDidLoad() {
super.viewDidLoad()
view = LoadingView(frame: view.frame)
view.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
}
func loadMoviesAndPresent() {
loadMovies() { [weak self] movies in
guard self != nil else {
return
}
print("Loaded \(movies.count) movies")
self!.movieListVC = MoviesListViewController(movies: movies)
self!.movieListVC.modalTransitionStyle = .crossDissolve
self!.show(self!.movieListVC, sender: self)
}
}
}
let rootVC = RootViewController(nibName: nil, bundle: nil)
rootVC.loadMoviesAndPresent()
PlaygroundPage.current.liveView = rootVC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment