Embedded ViewControllers
Evitando Massive View Controllers
Inácio Ferrarini - https://github.com/inacioferrarini
- Programador Java desde 2004- Programador iOS desde 2014- Graduado em Sistemas de
Informação pela FRB (2008)- Pós-Graduado em
Desenvolvimento de Aplicativos e Games para Dispositivos Móveis pela FIAP (2015)
- Contribuinte Open Source- Autor do POD York
Este Talk
- Model, View e Controller- Embedding via Storyboard- Embedding via Código- Tópicos Adicionais
Model, View e Controller
Model View
Controller
Notification&
KVOOutletDelegate
DataSourceTarget Action
Model, View e Controller (cont.)
Ao mesmo tempo em que View e Model possuem papéis bem definidos, não podemos dizer o mesmo do Controller.
Por uma falha comum de entendimento, assume-se que MVC seja apenas Model, View e Controller.
Entretanto, Model, View e Controller são os 3 tipos de objetos mais frequentes.
Objetos de apoio devem ser criados sempre que necessário.
Exemplos
Uma UITableViewCell responsável por lidar com uma target action - @IBAction - é uma “ViewViewController”.
class UITableViewCellViewControllerTableViewCell: UITableViewCell {
@IBOutlet weak var button: UIView! @IBAction func buttonAction() { } }
Exemplos
UITableViewController
UICollectionViewController
UITableViewCells
UICollectionViewDelegate
UICollectionViewDataSource
Ao "embeddar" um UICollectionView em uma UITableViewCell, o ideal é que o DataSource e Delegate não fiquem no ViewController “raiz”.
Desta forma, cada ViewController é responsável pelo Delegate e DataSource que use.
Neste caso, o UITableViewCell deve importar um UICollectionViewController ou similar.
Uso em Storyboards
Facilita o uso através de Container Views
Suporte a AutoLayout
Uso em Storyboards (cont.)
Utiliza a mecânica de segues ao carregar suas Embedded ViewControllers
class BaseViewController: UIViewController { var tableViewController: TableViewController? override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if let vc = segue.destinationViewController as? TableViewController { self.tableViewController = vc } } }
Embedded Collection View
Um UITableView
Cada UITableViewCell contém um UICollectionView
Cada UICollectionView possui UICollectionViewCells
Embedded Collection View (cont.)
UITableViewDelegate possui dois métodos importantes:
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath)
Embedded Collection View (cont.)
Estes métodos são chamados, respectivamente, quando o UITableViewController estiver prestes a exibir e a deixar de exibir a UITableViewCell em questão.
class DemoTableViewDataSource: NSObject, UITableViewDataSource { // MARK: - Embedded func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { if let cell = cell as? EmbededViewControllerTableViewCell { cell.embedInParentViewController(self.parentViewController) } } func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { if let cell = cell as? EmbededViewControllerTableViewCell { cell.unEmbedFromParentViewController() } } }
TableViewCell: Embedding with Code
class EmbededViewControllerTableViewCell: UITableViewCell { // MARK: - Properties var embeddedViewController: UIViewController? // MARK : - Embedding func embedInParentViewController(parentViewController: UIViewController) { if let embeddedViewController = self.embeddedViewController { parentViewController.addChildViewController(embeddedViewController) embeddedViewController.didMoveToParentViewController(parentViewController) self.contentView.addSubview(embeddedViewController.view) } } func unEmbedFromParentViewController() { if let embeddedViewController = self.embeddedViewController { embeddedViewController.view.removeFromSuperview() embeddedViewController.willMoveToParentViewController(nil) embeddedViewController.removeFromParentViewController() } } }
Tópicos Adicionais - Massive View Controller
O principal benefício que um Embedded ViewController provê é uma melhor organização e estruturação
Possibilita compor um ViewController a partir de ViewControllers menores;
ViewControllers podem ficar menores e mais específicos
Funcionalidades auxiliares (ex: Uma View com campo de texto que faz busca através de uma API) se tornam candidatos a Reúso
Para não gerar acoplamento, clojures ou notifications devem ser utilizados
Delegue para um DataSource Externo
class DemoTableViewDataSource: NSObject, UITableViewDataSource {
// MARK: - Properties let parentViewController: UIViewController // MARK: - Initialization init(parentViewController: UIViewController) { self.parentViewController = parentViewController } // MARK: - func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.viewControllers.count }
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("EmbededViewControllerTableViewCell", forIndexPath: indexPath) if let cell = cell as? EmbededViewControllerTableViewCell where indexPath.row < self.viewControllers.count { cell.embeddedViewController = viewControllers[indexPath.row] } return cell }
}
Delegue para um Delegate Externo
class DemoTableViewDelegate: NSObject, UITableViewDelegate {
// MARK: - Properties let parentViewController: UIViewController // MARK: - Initialization init(parentViewController: UIViewController) { self.parentViewController = parentViewController }
// …
}
Resumo
Embedded ViewControllers possibilitam ViewControllers mais específicos e reutilizáveis
É uma forma de evitar o Massive ViewController– Por sua vez, é um tópico vasto e recorrente– Geralmente causado por erosão arquitetural– Existem diversas alternativas, muitas delas são outras arquiteturas,
como V.I.P.E.R.
Referências Externas
Yorkhttps://github.com/inacioferrarini/Yorkhttps://cocoapods.org/pods/York
"Creating a Scrolling Filmstrip Within a UITableView”http://devblog.orgsync.com/2013/04/26/creating_scrolling_filmstrip_within_uitableview/
"View Controllers in Cells”http://khanlou.com/2015/04/view-controllers-in-cells/
Contato
[email protected]@concrete.com.br
LinkedInhttps://br.linkedin.com/in/inacioferrarini
Gitghubhttps://github.com/inacioferrarini
iOS Dev BR@inacioferrarini
Estamos Contratando!
Dúvidas?
www.concretesolutions.com.brblog.concretesolutions.com.br
Rio de Janeiro – Rua São José, 90 – cj. 2121Centro – (21) 2240-2030
São Paulo - Av. Nações Unidas, 11.541 3º andar - Brooklin - (11) 4119-0449