View Controller Containment Injecting Empty Views
//: Playground - noun: a place where people can play | |
import UIKit | |
import PlaygroundSupport | |
typealias JSONDictionary = [String:Any] | |
struct Resource<T> { | |
let url :URL | |
var parse :(Data) -> T? | |
} | |
struct Pokemon { | |
var name :String | |
} | |
extension Pokemon { | |
init?(dictionary :JSONDictionary) { | |
guard let name = dictionary["name"] as? String else { | |
fatalError("name not found") | |
} | |
self.name = name | |
} | |
} | |
class WebService { | |
func load<T>(resource :Resource<T>, completion:@escaping (T?) -> ()) { | |
URLSession.shared.dataTask(with: resource.url) { (data, _, _) in | |
DispatchQueue.main.async { | |
completion(resource.parse(data!)) | |
} | |
}.resume() | |
} | |
} | |
let pokemonURL = URL(string: "https://still-wave-26435.herokuapp.com/pokemon/all")! | |
let pokemonResource = Resource<[Pokemon]>(url: pokemonURL) { result in | |
let json = try! JSONSerialization.jsonObject(with: result, options: []) | |
let dictionaries = json as! [JSONDictionary] | |
return dictionaries.flatMap(Pokemon.init) | |
} | |
WebService().load(resource: pokemonResource) { pokemons in | |
print(pokemons!) | |
} | |
class EmptyViewController : UIViewController { | |
var message :String! | |
init(message :String) { | |
super.init(nibName: nil, bundle: nil) | |
self.message = message | |
} | |
required init?(coder aDecoder: NSCoder) { | |
fatalError("init(coder:) has not been implemented") | |
} | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
self.view.backgroundColor = UIColor.green | |
let messageLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 300, height: 44)) | |
messageLabel.text = self.message | |
self.view.addSubview(messageLabel) | |
} | |
} | |
class EmptyView : UIView { | |
init(delegate :UIViewController, message :String) { | |
super.init(frame: delegate.view.frame) | |
self.backgroundColor = UIColor.purple | |
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 300, height: 44)) | |
label.textColor = UIColor.white | |
label.text = message | |
self.addSubview(label) | |
} | |
required init?(coder aDecoder: NSCoder) { | |
fatalError("init(coder:) has not been implemented") | |
} | |
} | |
class PokemonTableViewController : UITableViewController { | |
var pokemons :[Pokemon]! | |
init() { | |
super.init(nibName: nil, bundle: nil) | |
self.pokemons = [Pokemon]() | |
populatePokemons() | |
} | |
private func populatePokemons() { | |
WebService().load(resource: pokemonResource) { pokemons in | |
if let pokemons = pokemons { | |
if pokemons.isEmpty { | |
self.view = EmptyView(delegate :self, message :"No Pokemons Found!") | |
} | |
} | |
} | |
} | |
init(pokemons :[Pokemon]) { | |
super.init(nibName: nil, bundle: nil) | |
self.pokemons = pokemons | |
} | |
override func numberOfSections(in tableView: UITableView) -> Int { | |
return 1 | |
} | |
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | |
return self.pokemons.count | |
} | |
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | |
let cell = UITableViewCell(style: .default, reuseIdentifier: "Cell") | |
cell.textLabel?.text = self.pokemons[indexPath.row].name | |
return cell | |
} | |
required init?(coder aDecoder: NSCoder) { | |
fatalError("init(coder:) has not been implemented") | |
} | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
self.view.backgroundColor = UIColor.white | |
} | |
} | |
class ContainerViewController : UIViewController { | |
init<T>(resource :Resource<T>, build:@escaping (T) -> UIViewController) { | |
super.init(nibName: nil, bundle: nil) | |
WebService().load(resource: resource) { result in | |
let content = build(result!) | |
self.add(content :content) | |
} | |
} | |
private func add(content :UIViewController) { | |
// Remove any existing child controllers. | |
for child in childViewControllers { | |
child.willMove(toParentViewController: nil) | |
child.view.removeFromSuperview() | |
child.removeFromParentViewController() | |
} | |
addChildViewController(content) | |
content.view.frame = self.view.bounds | |
content.view.translatesAutoresizingMaskIntoConstraints = false | |
self.view.addSubview(content.view) | |
content.view.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true | |
content.view.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true | |
content.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true | |
content.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true | |
content.didMove(toParentViewController: self) | |
} | |
required init?(coder aDecoder: NSCoder) { | |
fatalError("init(coder:) has not been implemented") | |
} | |
} | |
let containerVC = ContainerViewController(resource: pokemonResource) { pokemons in | |
if pokemons.isEmpty { | |
return EmptyViewController(message : "No Pokemons Found!") | |
} else { | |
return PokemonTableViewController(pokemons :pokemons) | |
} | |
} | |
let pokemonTVC = PokemonTableViewController() | |
PlaygroundSupport.PlaygroundPage.current.liveView = containerVC | |
PlaygroundSupport.PlaygroundPage.current.needsIndefiniteExecution = true | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment