Alura > Cursos de Mobile > Cursos de iOS > Conteúdos de iOS > Primeiras aulas do curso iOS com view code: construção de layouts com tabelas

iOS com view code: construção de layouts com tabelas

Construindo uma tabela - Apresentação

Olá, o meu nome é Giovanna Moeller e eu sou instrutora aqui na Alura.

Audiodescrição: Giovanna Moeller se identifica como uma mulher branca, de cabelos loiros, lisos e longos. Seu rosto é oval. Tem olhos escuros, nariz fino e lábios grossos. Usa uma camiseta azul-escuro com o logotipo da Alura. Ao fundo, uma parede lisa iluminada em tons de rosa com uma prateleira de livros e um painel LED luminoso com a palavra "alura" à esquerda, e com um vaso de plantas à direita.

Queremos te dar as boas-vindas ao curso de iOS com ViewCode, focado na criação de layouts com tabelas.

Entendendo o Projeto

Durante este curso, vamos continuar com um projeto chamado Cinetopia, no qual vamos construir a tela de filmes. Nessa tela de filmes, temos os dados representados em formato de tabela, com cada filme aparecendo como uma célula desta tabela. Também temos uma barra de pesquisa no topo da tela da aplicação que permite filtrar esses filmes.

O que Aprenderemos?

É muito importante aprender sobre isso, porque tabelas são muito utilizadas em aplicativos iOS, e claro, utilizando a melhor prática do mercado, que é a abordagem programática, ou seja, o ViewCode.

Pré-requisitos

Não se preocupe, pois temos cursos com esses conteúdos aqui na plataforma.

Esperamos que você tenha se animado. Te esperamos na primeira aula!

Construindo uma tabela - Criando uma tabela

A nossa tarefa durante este curso é construir a tela de filmes com uma tabela que representa os filmes. Em cada célula dessa tabela, ou seja, em cada linha, vamos ter o pôster, o nome e a data de lançamento do filme. Vamos começar construindo essa tabela dentro da classe MoviesViewController.

Construindo a Tabela de Filmes

Vamos voltar no código dessa classe e começar criando uma variável. Logo acima da função viewDidLoad(), vamos começar escrevendo private lazy var tableView: e ela será do tipo UITableView. Vamos adicionar um igual, um bloco de chaves e após ele, um bloco de parênteses.

class MoviesViewController: UIViewController { 

    private lazy var tableView: UITableView = {
    
    }()
    
    override func viewDidLoad() {
        // Código omitido
    }
    // Código omitido
}

Dentro dessa função, vamos começar escrevendo let tableView = UITableView(). Não podemos esquecer de adicionar o translatesAutoresizingMaskIntoConstraints = false na linha de baixo para ter as constraints (restrições) de forma programática. Vamos colocar uma cor de fundo só para vermos ela aparecendo. Então, desceremos outra linha para escrever tableView.backgroundColor = .blue e return tableView, uma em cada linha.

class MoviesViewController: UIViewController { 

    private lazy var tableView: UITableView = {
        let tableView = UITableView()
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.backgroundColor = .blue
        return tableView
    }()
    
    // Código omitido
}

Agora, nós vamos criar as duas funções, a addSubviews() e também a setupConstraints(). Vamos fazer isso logo acima da função setupNavigationBar(). Então, escreveremos private func setupConstraints() e um bloco de chaves. Acima dela, escreveremos a private func addSubviews() junto a um bloco de chaves.

 private func addSubviews() {
 
 }
 
private func setupConstraints() {

}
 
private func setupNavigationBar() {
    // Código omitido
}

Esse é um jeito que eu, Giovanna, gosto de fazer: criar as funções com esses nomes. Mas, não tem jeito certo ou errado, é só o jeito que eu prefiro.

Entre as chaves da função addSubviews(), vamos adicionar um view.addSubview(tableView). Entre as chaves da setUpConstraints(), vamos utilizar o NSLayoutConstraint.activate(), passando entre parênteses um array (arranjo), dentro do qual vamos colocar as constraints da tabela.

 private func addSubviews() {
     view.addSubview(tableView)
 }
 
private func setupConstraints() {
    NSLayoutConstraint.activate([])
}

Queremos que essa tabela ocupe toda a tela. Para isso, faremos um tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor) dentro do arranjo. Com isso, o topo da tabela será igual ao topo da tela. Adicionaremos uma vírgula, desceremos uma linha e adicionaremos os seguintes parâmetros, um em cada linha, separados por vírgulas:

private func addSubviews() {
     view.addSubview(tableView)
 }
 
private func setupConstraints() {
    NSLayoutConstraint.activate([
        tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
        tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
    ])
}

Vamos chamar as funções addSubviews() e setUpConstraints() dentro de viewDidLoad(), logo após chamar a setupNavigationBar().

override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = .background
    setupNavigationBar()
    addSubviews()
    setupConstraints()
    
    // Do any aditional setup after loading the view.
}

Agora sim, daremos o "Command+R" para executar esse código e abrir o emulador. Nele, clicaremos em "Quero começar!" e seremos direcionados para a tela "Filmes populares" que exibe somente a cor azul. Com isso, já temos, então, a nossa tabela criada.

Vamos trocar a cor de fundo para ficar a mesma da tela, esse roxo escuro. Contudo, se removermos a propriedade backgroundColor da tableView e executar a aplicação com "Command+R", a tela "Filmes populares", referente à tabela, fica branca.

Para que ela seja a mesma cor do fundo, ou colocamos a cor de fundo como backgroundColor, que temos lá nos assets, ou podemos escrever tableView.backgroundColor = .clear, para "limpar" o fundo e torná-la da mesma cor do fundo da tela. Faremos do segundo modo.

private lazy var tableView: UITableView = {
    let tableView = UITableView()
    tableView.translatesAutoresizingMaskIntoConstraints = false
    tableView.backgroundColor = .clear
    return tableView
}()

Temos a estrutura da tabela criada. A seguir, precisamos adicionar dados a essa tabela.

Construindo uma tabela - Conhecendo o UITableViewDataSource

Vamos imaginar que nós temos uma lista de nomes e queremos exibir cada nome em uma célula dessa tabela. Quando falamos em célula, queremos dizer uma linha, um item desta tabela. Então, vamos começar fazendo isso.

Exibindo Nomes na Tabela

Primeiro, vamos criar um array (arranjo) de nomes. Acima do tableView, vamos definir um var names, que é do tipo array de string ([String]). Adicionaremos um igual e um par de colchetes, dentro do qual vamos definir alguns nomes entre aspas duplas, como, por exemplo, Ana, Giovanna, Lucas, e Daniel.

class MoviesViewController: UIViewController { 

    var names: [String] = [
        "Ana", "Giovanna", "Lucas", "Daniel"
    ]
    
    private lazy var tableView: UITableView = {
        // Código omitido
    }()
    
    // Código omitido
}

Não se preocupe, porque depois nós voltaremos ao contexto de filmes e faremos células mais customizadas e personalizadas.

Agora, como falamos para a tabela que vamos exibir cada item deste array em uma célula? Precisamos fazer com que a classe MoviesViewController esteja em conformidade com um protocolo chamado UITableViewDataSource, que será a fonte de dados da tabela.

Logo após o UITableViewController, na linha que declara a classe MoviesViewController, vamos colocar uma vírgula e um UITableViewDataSource.

class MoviesViewController: UIViewController, UITableViewDataSource { 

    var names: [String] = [
        "Ana", "Giovanna", "Lucas", "Daniel"
    ]
    
    private lazy var tableView: UITableView = {
        // Código omitido
    }()
    
    // Código omitido
}

Ele já está mostrando um erro antes mesmo de tentarmos executar esse código. Esse erro nos diz que o tipo MoviesViewController não está conformando ao protocolo UITableViewDataSource.

Devemos lembrar que um protocolo é um conjunto de regras que precisamos implementar. Este protocolo, UITableViewDataSource, contém dois métodos que são obrigatórios de se implementar. Como não estamos implementando ainda, ele está dando esse erro.

No canto inferior direito da mensagem de erro, vamos clicar em "Fix" (consertar), e ele vai adicionar um método novo acima do arranjo var names.

class MoviesViewController: UIViewController, UITableViewDataSource { 

    func tableView(_ tableView: UITableView, cellForRowAr indexPath: IndexPath) -> UITableViewCell {
        code
    }

    var names: [String] = [
        "Ana", "Giovanna", "Lucas", "Daniel"
    ]

    // Código omitido
}

Ele vai continuar dando o erro, porque, como dito, precisamos implementar dois métodos necessários. Vamos clicar em "Fix" novamente, e agora, sim, temos dois métodos referentes ao UITableViewDataSource acima do arranjo names.

class MoviesViewController: UIViewController, UITableViewDataSource { 
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        code
    }

    func tableView(_ tableView: UITableView, cellForRowAr indexPath: IndexPath) -> UITableViewCell {
        code
    }

    var names: [String] = [
        "Ana", "Giovanna", "Lucas", "Daniel"
    ]

    // Código omitido
}

O primeiro superior recebe um parâmetro chamado NumberOfRowsInSection, que retorna um inteiro. Este método retorna a quantidade de linhas que a tabela terá. Dentro desse código, poderíamos simplesmente escrever return 4. Usaremos o valor 4 porque o names, que definimos abaixo das funções, possui quatro elementos.

Contudo, isso está muito estático. Se adicionarmos um novo nome no array, precisamos acessar o interior dessa tableView e mudar o valor para 5, o que não é muito performático. Então, nesse caso, vamos dar um return names.count, que representa quantos elementos temos dentro do array names.

class MoviesViewController: UIViewController, UITableViewDataSource { 
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return names.count
    }

    func tableView(_ tableView: UITableView, cellForRowAr indexPath: IndexPath) -> UITableViewCell {
        code
    }

    var names: [String] = [
        "Ana", "Giovanna", "Lucas", "Daniel"
    ]

    // Código omitido
}

Vamos executar esse código, mas antes precisamos implementar algo na segunda função tableView. Como não vamos trabalhar com isso nesse momento, vamos dar um return UITableViewCell(), pois é o retorno que ele pede.

Não se preocupe porque voltaremos nesse método em breve, já que é por meio dele que conseguimos adicionar, por exemplo, um nome na célula.

class MoviesViewController: UIViewController, UITableViewDataSource { 
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return names.count
    }

    func tableView(_ tableView: UITableView, cellForRowAr indexPath: IndexPath) -> UITableViewCell {
        return UITableViewCell()
    }

    var names: [String] = [
        "Ana", "Giovanna", "Lucas", "Daniel"
    ]

    // Código omitido
}

Vamos executar esse código com o "Command+R" e veremos no emulador que nada aconteceu ainda. Na tela "Filmes populares", se tentássemos clicar na tabela, ela deveria pelo menos mostrar as quatro linhas que implementamos no primeiro método que recebe o parâmetro NumberOfRowsInSection.

Nada aconteceu porque está faltando fazer uma configuração. Para essa tabela funcionar corretamente, ela precisa saber quem é a sua fonte de dados.

Vamos voltar para o código. Entre as chaves da função private lazy var tableView, na qual criamos a tabela, logo abaixo do tableView.backgroundColor = .clear, vamos escrever tableView.dataSource = self.

O self representa a classe MoviesViewController. Estamos dizendo que a MoviesViewController, ou seja, a tela, é a fonte de dados para a tabela.

class MoviesViewController: UIViewController, UITableViewDataSource { 
    
    // Código omitido

    var names: [String] = [
        "Ana", "Giovanna", "Lucas", "Daniel"
    ]
    
    private lazy var tableView: UITableView = {
        let tableView = UITableView()
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.backgroundColor = .clear
        tableView.dataSource = self
        return tableView
    }()

    
}

Agora, vamos executar novamente o aplicativo, clicando em "Quero começar!". Na tela "Filmes populares", já conseguimos pelo menos ver as quatro linhas. Se clicarmos em uma linha, conseguimos vê-la sendo preenchida pela cor cinza da seleção.

Já conseguimos menos executar o primeiro método referente ao UITableViewDataSource. A seguir, precisamos exibir cada nome do array nestas células.

Sobre o curso iOS com view code: construção de layouts com tabelas

O curso iOS com view code: construção de layouts com tabelas possui 91 minutos de vídeos, em um total de 50 atividades. Gostou? Conheça nossos outros cursos de iOS em Mobile, ou leia nossos artigos de Mobile.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda iOS acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas