UIViewControll er UIViewControll er UIViewControll er Fluxos & Bibliotecas Rotas Transição do App monolítico para abordagem de produtos Alavancagem do poder das Hyper Media APIs Eram necessários fluxos desacoplados
er UIViewControll er UIViewControll er UIViewControll er Explicação de alto nível - RoutingHub: tudo começa & todos tem acesso - Encontra um RouteDescriptor: Abstraí as necessidades do Coordinator - Coordinator: Maneja o fluxo (apresenta UIViewControllers) - Router: Tudo acontece dentro de um contexto de apresentação
URL(string: "nuapp://domain")) .subscribe(onNext: { state in //React to state changes } Router Fluxo RoutingHu b RouteDescript or Coordinator UIViewController UIViewController UIViewController UIViewController Podemos ouvir mudanças de estado do fluxo
URL(string: "nuapp://domain")) .subscribe(onNext: { state in //React to state changes }, onError: { error in //Handle flow errors } Router Fluxo RoutingHu b RouteDescript or Coordinator UIViewController UIViewController UIViewController UIViewController Podemos ouvir erros no fluxo
URL(string: "nuapp://domain")) .subscribe(onNext: { state in //React to state changes }, onError: { error in //Handle flow errors }, onCompleted: { //Perform finishing actions }) Router Fluxo RoutingHu b RouteDescript or Coordinator UIViewController UIViewController UIViewController UIViewController Saber quando o fluxo acabou e fazer algo em resposta
func start(url: URL) -> Observable<RoutingState> { guard let router = self.router else { return .error(RoutingError.routerUnavailable) } } } Router Fluxo RoutingHu b RouteDescript or Coordinator UIViewController UIViewController UIViewController UIViewController Verifica se tem contexto; Senão, é um erro e podemos jogar pra cima
router: Router? var descriptors: [RouteDescriptor] = [] func register(descriptor: RouteDescriptor) func register(router: Router) … } Router Fluxo RoutingHu b RouteDescript or Coordinator UIViewController UIViewController UIViewController UIViewController RoutingHub é o ponto central de roteamento - Mantém as rotas conhecidas - Mantém o contexto atual de apresentação - Registro dinâmico de rotas e contexto
routingHub.register(descriptor: cardActivationRoute) routingHub.register(descriptor: helpRoute) … routingHub.start(url: URL(string: "nuapp://domain")) Router Fluxo RoutingHu b RouteDescript or Coordinator UIViewController UIViewController UIViewController UIViewController - Assim que podemos registrar vários Endpoints - Depois de registrar, podemos só passar a URL
de vida protocol RouteDescriptor: AnyObject { func match(url: URL) -> Bool func start(url: URL, on context: UIViewController) -> Observable<RoutingState> } Router Fluxo RoutingHu b RouteDescript or Coordinator UIViewController UIViewController UIViewController UIViewController Interface do RouteDescriptor - Match pra dizer que rotas vai tratar - Start pra fazer o trabalho de fato
Bool { return url.host == "domain" //Matches xxx://domain } } Router Fluxo RoutingHu b RouteDescript or Coordinator UIViewController UIViewController UIViewController UIViewController Como implementar um desses? Primeiro vc escreve a regra de match
Bool { return url.host == "domain" //Matches xxx://domain } func start(url: URL, on context: UIViewController) -> Observable<RoutingState> { return Observable.create { (observer) -> Disposable in } } } Router Fluxo RoutingHu b RouteDescript or Coordinator UIViewController UIViewController UIViewController UIViewController Exemplo de como envelopar uma rota num Observable Primeiro cria o Observable.create. Lá vamos transformar os eventos do Coordinator nos eventos do Observable
Bool { return url.host == "domain" //Matches xxx://domain } func start(url: URL, on context: UIViewController) -> Observable<RoutingState> { return Observable.create { (observer) -> Disposable in let coordinator = SomeCoordinator(context: context) do { try coordinator.start(onCompleted: observer.onCompleted) } catch { observer.onError(error) } return Disposables.create { coordinator.dismiss() } } } } Router Fluxo RoutingHu b RouteDescript or Coordinator UIViewController UIViewController UIViewController UIViewController Tratamos o caso de dismiss da rota Quando jogamos o Observable fora, entendemos que não queremos mais a rota.
Observable<RoutingState> enum RoutingState { } Router Fluxo RoutingHu b RouteDescript or Coordinator UIViewController UIViewController UIViewController UIViewController Como passar o estado da rota? - RoutingState comunica isso
Observable<RoutingState> enum RoutingState { case preparing } Router Fluxo RoutingHu b RouteDescript or Coordinator UIViewController UIViewController UIViewController UIViewController Estado de Preparing (fazendo request, I/O, computação, etc..) - Tela ainda não foi apresentada
Observable<RoutingState> enum RoutingState { case preparing case started } Router Fluxo RoutingHu b RouteDescript or Coordinator UIViewController UIViewController UIViewController UIViewController Started: tela já foi apresentada
Observable<RoutingState> enum RoutingState { case preparing case started case produced } Router Fluxo RoutingHu b RouteDescript or Coordinator UIViewController UIViewController UIViewController UIViewController Produced: Algo aconteceu na rota que quem chama pode estar interessado
er UIViewControll er UIViewControll er Abstrair apresentação/passagem de informação entre VCs: Coordinator - Encapsula VCs em uma unidade de fluxo - Ele sabe a lógica de apresentação - Ele sabe passar dados de um VC para o outro
de um fluxo Abstrair apresentação/passagem de informação entre VCs: Coordinator - Encapsula VCs em uma unidade de fluxo - Ele sabe a lógica de apresentação - Ele sabe passar dados de um VC para o outro
UIViewController Abstrair apresentação/passagem de informação entre VCs: Coordinator - Encapsula VCs em uma unidade de fluxo - Ele sabe a lógica de apresentação - Ele sabe passar dados de um VC para o outro
er UIViewControll er UIViewControll er UIViewControll er Explicação de alto nível - RoutingHub: tudo começa & todos tem acesso - Encontra um RouteDescriptor: Abstraí as necessidades do Coordinator - Coordinator: Maneja o fluxo (apresenta UIViewControllers) - Router: Tudo acontece dentro de um contexto de apresentação