Skip to content

Instantly share code, notes, and snippets.

@runys
Created March 8, 2017 13:48
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save runys/6d1e41d8498222e880663bbc871b120d to your computer and use it in GitHub Desktop.
Save runys/6d1e41d8498222e880663bbc871b120d to your computer and use it in GitHub Desktop.
Tutorial about how to create a simple page view application in iOS 10 with Swift 3. Originally create to be seen in a playground.
/*:
## Tutorial de UIPageViewController
Referências:
- [How to Use UIPageViewController in Swift 2.2](https://spin.atomicobject.com/2015/12/23/swift-uipageviewcontroller-tutorial/)
- [How to Move Page Dots in a UIPageViewController with Delegation](https://spin.atomicobject.com/2016/02/11/move-uipageviewcontroller-dots/)
- [](https://developer.apple.com/reference/uikit/uipageviewcontroller)
- [](https://developer.apple.com/reference/uikit/uipageviewcontrollerdatasource)
- [](https://developer.apple.com/reference/uikit/uipageviewcontrollerdelegate)
Olá amigos! Vamos aprender como utilizar Page View Controller para fazermos aquela tela bacana de tutorial.
1. Crie seu projeto um novo projeto no XCode, uma `Single View Application`.
Antes de partirmos pro código, temos que fazer umas coisinhas no `Main.storyboard`
### No `Main.storyboard`:
2. Apague a `ViewController` que já veio pronta pra você.
3. Adicione uma `Page View Controller` e a defina como tela inicial (`Is Initial View Controller`).
4. Na aba `Attributes` defina a propriedade `Transition Style` da Page View Controller como `Scroll`
5. Crie três `View Controller`s e pinte a `View` de cada uma com uma cor (Vermelho, Azul, Amarelo).
Muita atenção nestes próximos passos. Para cada `View Controller` que você criou, selecione-a e:
6. Vá no `Identity Inspector`.
7. Na seção `Identity` coloque o nome da cor no campo `Storyboard ID` (Vermelho, Azul, Amarelo). Lembre-se de apertar `enter`.
8. Marque o campo `Use Storyboard ID`.
### Classe TutorialPageViewController
Agora vamos ao código, shall we?
1. Crie um novo arquivo `Cocoa Touch Class`.
2. O `nome` da classe será `TutorialViewController`.
3. Ele será `subclass` de `UIPageViewController`.
4. Vá no `Main.storyboard` e selecione seu `Page View Controller`.
5. Com ele selecionado vá na seção `Identity` e defina a `class` como `TutorialViewController`.
*/
import UIKit
class TutorialViewController: UIPageViewController {
// 1. Precisamos do nosso UIPageControl para mostrar em que página o usuário esta
var paginador = UIPageControl()
// 2. Vamos inserir nosso `paginador` na nossa `view` assim que ela for inicializado
func inicializarPaginador() {
// 3. Definimos o número de páginas (vamos criar esse array já já)
self.paginador.numberOfPages = self.tutorialViewControllers.count
// 4. Definimos a página inicial do paginador
self.paginador.currentPage = 0
let meioDaTela = self.view.frame.width / 2
let parteDeBaixoDaTela = self.view.frame.height - 16
// 5. Posicionamos o paginador no centro e na parte de baixo da tela
self.paginador.frame.origin = CGPoint(x: meioDaTela, y: parteDeBaixoDaTela)
// 6. Adicionamos nosso paginador na nossa `view`, agora ele está aparecendo na tela
self.view.addSubview(self.paginador)
}
// 1. Precisamos agora de uma forma de pegar as View Controllers la no Storyboard.
// Este método faz exatamente isso!
// Você diz pra ele o identificador da View Controller e ele te traz ela para que você use :)
private func viewControllerChamada(_ identifier: String) -> UIViewController {
// Pegamos o Main.storyboard, é nele que vamos buscar nossas View Controllers
let storyboard = UIStoryboard(name: "Main", bundle: nil)
// Agora instanciamos a View Controller de acordo com o identificador dela
let vc = storyboard.instantiateViewController(withIdentifier: identifier)
return vc
}
// 1. Agora vamos definir as páginas do nosso tutorial, as View Controllers que irão aparecer para o usuário
// Esta é uma propriedade `lazy`, ou seja, só é inicializada quando for utilizada
lazy var tutorialViewControllers: [UIViewController] = {
return [
self.viewControllerChamada("Vermelho"), // Primeira página
self.viewControllerChamada("Azul"), // Segunda página
self.viewControllerChamada("Vermelho") // Terceira página
]
}()
// Agora nós temos tudo que precisamos para paginar:
// - Temos o page control para mostrar pro usuário em que página ele está
// - Temos o array com as páginas
// Precisamos configurar nossa Page View Controller para utilizar nossas
// view controllers na paginação
override func viewDidLoad() {
super.viewDidLoad()
// 1. Vamos definir que o `dataSource` e o `delegate` da nossa Page View Controller
// serão implementados em nossa classe.
self.delegate = self
self.dataSource = self
// Vai aparecer um erro por enquanto, mas já já ele some
// Agora vamos definir a página inicial da nossa Page View Controller
// 2. Pegamos a view controller na primeira posição do nosso array
if let primeiraViewController = self.tutorialViewControllers.first {
// 3. Definimos ela como a view controller inicial da nossa Page View Controller
self.setViewControllers([primeiraViewController],
direction: .forward,
animated: true,
completion: nil)
}
// 4. Por fim inicializamos nosso paginador
self.inicializarPaginador()
}
}
/*:
Perfeito! Até aqui só temos 2 errinhos nas linhas de delegate e dataSource, mas vamos resolver agora!
Como nós falamos para nossa Page View Controller que seus métodos de delegate e data source estarão implementados na nossa classe precisamos implementar os protocolos e os métodos necessários para que ela funcione.
Iremos fazer isso em uma extensão da classe para que nosso código fique mais limpo e organizado.
*/
// 1. Criamos nossa extension e declaramos que vamos implementar os protocolos
// - UIPageViewControllerDataSource
// - UIPageViewControllerDelegate
extension TutorialViewController: UIPageViewControllerDataSource, UIPageViewControllerDelegate {
// 2. O primeiro método que iremos implementar é o método que define qual a View Controller que vem antes da View Controller atual na nossa paginação
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
// Primeiro precisamos pegar o indice da view controller no nosso array
// Precisamos do indice para saber quem vem ANTES da view controller atual
guard let indiceDaViewController = self.tutorialViewControllers.index(of: viewController) else {
return nil
}
// Com isso podemos definir qual é o índice anterior ao atual
let indiceAnterior = indiceDaViewController - 1
// Se o indice anterior for NEGATIVO então retornamos `nil`
if indiceAnterior < 0 {
return nil
}
// Se o indice anterior for MAIOR QUE a quantidade de elemento no nosso array, também retornamos `nil`
if indiceAnterior > self.tutorialViewControllers.count {
return nil
}
// Após testar a validade do indice, retornamos a View Controller do nosso array correspondente a essa posição
return self.tutorialViewControllers[indiceAnterior]
}
// 3. O segundo método que iremos implementar é o que define qual View Controller vem depois da View Controller atual na nossa paginação
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
// Primeiro precisamos pegar o indice da view controller no nosso array
// Precisamos do indice para saber quem vem DEPOIS da view controller atual
guard let indiceDaViewController = self.tutorialViewControllers.index(of: viewController) else {
return nil
}
// Com isso podemos definir qual é o índice após ao atual
let proximoIndice = indiceDaViewController + 1
// Precisamos saber quantas páginas tem no total na nossa Page View Controller
// Para isso pegamos a quantidade de elementos no nosso array de View Controllers
let quantidadeDeViewControllers = self.tutorialViewControllers.count
// Se o proximo indice for IGUAL a quantidade de controllers no array retornamos `nil`
if proximoIndice == quantidadeDeViewControllers {
return nil
}
// Se o próximo índice for MAIOR QUE a quantidade de de controllers no array retornamos `nil`
if proximoIndice > quantidadeDeViewControllers {
return nil
}
// Após testar a validade do indice, retornamos a View Controller do nosso array correspondente à proxima view controller na paginação
return self.tutorialViewControllers[proximoIndice]
}
// 4. Por fim vamos implementar o método para atualizarmos o nosso paginador quando o usuário passar a página no Page View Controller
// Ess método é chamado após a animação de transição entre as páginas
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
// A primeira coisa que precisamos saber é qual a view controller atual no nosso Page View. Com isso será possivel saber se o usuário passou ou não a página após a animação ser concluída
// A propriedade `self.viewControllers` representa as View Controllers da sua Page View Controller. Como herdamos de UIPageViewController já temos acesso a essa propriedade.
// O primeiro elemento deste array representa a view controller atual na paginação
if let viewControllerAtual = self.viewControllers?.first {
// Com a view controller atual em mãos podemos saber em qual posição do nosso array de view controllers ela se encontra
if let indice = self.tutorialViewControllers.index(of: viewControllerAtual) {
// A página no nosso paginador é correspondente ao indice da View Controller atual no nosso array de View Controllers
self.paginador.currentPage = indice
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment