Created
January 11, 2017 20:41
-
-
Save azamsharp/4836d90bc50b7ad52c042a9bb9e92e46 to your computer and use it in GitHub Desktop.
View Controller Containment Injecting Empty Views
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: 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