Se não houver resultados do Table View, exibir “No Results” na tela


114

Eu tenho um tableview, onde às vezes pode não haver resultados para listar, então eu gostaria de colocar algo que diz "nenhum resultado" se não houver resultados (um rótulo ou uma célula de exibição de tabela?).

Existe uma maneira mais fácil de fazer isso?

Eu tentaria um labelatrás do e, em tableviewseguida, esconder um dos dois com base nos resultados, mas como estou trabalhando com um TableViewControllere não com um normal, ViewControllernão tenho certeza se isso é inteligente ou factível.

Também estou usando Parsee criando subclasses como PFQueryTableViewController:

@interface TableViewController : PFQueryTableViewController

Posso fornecer quaisquer detalhes adicionais necessários, basta me avisar!

TableViewController Cena no Storyboard:

insira a descrição da imagem aqui

EDIT: Por Midhun MP, aqui está o código que estou usando

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    NSInteger numOfSections = 0;
    if ([self.stringArray count] > 0)
    {
        self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
        numOfSections                 = 1;
        //yourTableView.backgroundView   = nil;
        self.tableView.backgroundView = nil;
    }
    else
    {
        UILabel *noDataLabel         = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.tableView.bounds.size.width, self.tableView.bounds.size.height)];
        noDataLabel.text             = @"No data available";
        noDataLabel.textColor        = [UIColor blackColor];
        noDataLabel.textAlignment    = NSTextAlignmentCenter;
        //yourTableView.backgroundView = noDataLabel;
        //yourTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
        self.tableView.backgroundView = noDataLabel;
        self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    }

    return numOfSections;
}

E aqui está a visualização que estou obtendo, ela ainda tem linhas separadoras. Tenho a impressão de que esta é uma pequena alteração, mas não tenho certeza de por que as linhas separadoras estão aparecendo.

insira a descrição da imagem aqui


Acho que o truque era configurar footerView vazio em tableview para se livrar das linhas.
Ben Sinclair,

@Andy O que você quer dizer com isso?
SRMR

Não use a solução adicionada a esta questão. Os métodos de fonte de dados de exibição de tabela nunca devem fazer mais do que deveriam. numberOfSectionsdeve retornar uma contagem e é isso. O mesmo para numberOfRowsInSection. Eles podem ser chamados várias vezes a qualquer momento. Nunca atualize visualizações ou dados, nem faça nada, exceto retornar uma contagem. A lógica para atualizar as visualizações nunca deve estar nesses métodos.
rmaddy

Respostas:


206

Você pode conseguir isso facilmente usando a backgroundViewpropriedade de UITableView.

Objetivo C:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    NSInteger numOfSections = 0;
    if (youHaveData)
    {
        yourTableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
        numOfSections                = 1;
        yourTableView.backgroundView = nil;
    }
    else
    {   
        UILabel *noDataLabel         = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, yourTableView.bounds.size.width, yourTableView.bounds.size.height)];
        noDataLabel.text             = @"No data available";
        noDataLabel.textColor        = [UIColor blackColor];
        noDataLabel.textAlignment    = NSTextAlignmentCenter;
        yourTableView.backgroundView = noDataLabel;
        yourTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    }

    return numOfSections;
}

Rápido:

func numberOfSections(in tableView: UITableView) -> Int
{
    var numOfSections: Int = 0
    if youHaveData
    {
        tableView.separatorStyle = .singleLine
        numOfSections            = 1
        tableView.backgroundView = nil
    }
    else
    {
        let noDataLabel: UILabel  = UILabel(frame: CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: tableView.bounds.size.height))
        noDataLabel.text          = "No data available"
        noDataLabel.textColor     = UIColor.black
        noDataLabel.textAlignment = .center
        tableView.backgroundView  = noDataLabel
        tableView.separatorStyle  = .none
    }
    return numOfSections
}

Referência Referência de classe UITableView

backgroundView Propriedade

A vista de fundo da vista de mesa.

Declaração

Rápido

var backgroundView: UIView?

Objective-C

@property(nonatomic, readwrite, retain) UIView *backgroundView

Discussão

A visualização do plano de fundo da visualização da tabela é redimensionada automaticamente para corresponder ao tamanho da visualização da tabela. Esta visão é colocada como uma subvisão da visão de tabela atrás de todas as células, visões de cabeçalho e visões de rodapé.

Você deve definir esta propriedade como nulo para definir a cor de fundo da visualização da tabela.


Obrigado pela resposta! Isso significa que preciso de uma tableViewválvula de escape para poder fazer yourTableView.backgroundView? Estou usando um, TableViewControllerentão não tenho uma saída para ele agora, é por isso que estou me perguntando.
SRMR

1
UITableViewControllerjá tem uma propriedade chamada, tableViewentão você não precisa criar uma
Cihan Tek

self.tableView
Ok

1
Correção. Após testes adicionais, eu realmente tive que fazer a linha que mencionei retornar o mesmo valor. numOfSections = 1. Se eu definir zero e minha visualização de tabela estiver vazia, funciona, mas quando eu crio uma célula e a excluo, em vez de excluir e mostrar a mensagem, ela trava com o seguinte erro. *** Encerrando aplicativo devido à exceção não detectada 'NSInternalInconsistencyException', motivo: 'UITableView bug interno: não é possível gerar um novo mapa de seção com contagem de seção antiga: 1 e nova contagem de seção: 0'. Não sei por que retornar o mesmo valor funciona, mas funciona e funciona como deveria.
ChrisOSX

2
Não use esta solução. Os métodos de fonte de dados de exibição de tabela nunca devem fazer mais do que deveriam. numberOfSectionsdeve retornar uma contagem e é isso. O mesmo para numberOfRowsInSection. Eles podem ser chamados várias vezes a qualquer momento. Nunca atualize visualizações ou dados, nem faça nada, exceto retornar uma contagem. A lógica para atualizar as visualizações nunca deve estar nesses métodos.
rmaddy

107

Para Xcode 8.3.2 - Swift 3.1

Aqui está uma maneira não tão conhecida, mas incrivelmente fácil de conseguir adicionar uma visualização "Sem Itens" a uma visualização de tabela vazia que remonta ao Xcode 7. Deixarei para você controlar a lógica que adiciona / remove o view para a visão de fundo da tabela, mas aqui está o fluxo para um storyboard Xcode (8.3.2):

  1. Selecione a cena no Storyboard que contém sua visualização de mesa.
  2. Arraste um UIView vazio para o "Scene Dock" dessa cena

insira a descrição da imagem aqui

  1. Adicione um UILabel e quaisquer restrições à nova visão e, em seguida, crie um IBOutlet para essa visão

insira a descrição da imagem aqui

  1. Atribua essa visualização ao tableView.backgroundView

insira a descrição da imagem aqui

  1. Veja a magia!

insira a descrição da imagem aqui

Em última análise, isso funciona sempre que você deseja adicionar uma visualização simples ao controlador de visualização que não deseja necessariamente que seja exibida imediatamente, mas que também não deseja codificar manualmente.


1
Essa técnica funciona para qualquer coisa para a qual você precise de uma visualização simples. Eu também o usei para cabeçalhos de seção de tabela personalizados. Na verdade, você pode usá-lo para qualquer coisa para a qual precise de uma visualização. Basta fazer referência por meio de um IBOutlet e adicioná-lo como subvisualização em qualquer lugar que você precise de uma visão personalizada.
Paul Bonneville

Como @gmogames disse, depois de fazer IOS por 2 anos, esta é a primeira vez que conheço o background do tableView!. obrigado cara
Ali Adil

1
Obrigado por isso. Apenas para colocá-lo lá fora, eu tive que usar tableView.separatorStyle = .none e redimensionar o UIView padrão para ver o backgroundView. Estou usando o Xcode 9.4 com Swift 4.
Hammad Tariq de

Como você posiciona a visualização personalizada?
Nol4635

1
@ Nol4635 No caso do fundo da tableview, você apenas atribui a visão que criou como um IBOutlet ao fundo da tableview ou, se quiser apenas adicionar a visão a qualquer outra visão, pode simplesmente adicioná-la como uma subvisualização. Você terá que definir os valores do quadro, mas é como qualquer outra visualização.
Paul Bonneville

30

Versão Swift do código acima: -

func numberOfSectionsInTableView(tableView: UITableView) -> Int {

    var numOfSection: NSInteger = 0

    if CCompanyLogoImage.count > 0 {

        self.tableView.backgroundView = nil
        numOfSection = 1


    } else {

        var noDataLabel: UILabel = UILabel(frame: CGRectMake(0, 0, self.tableView.bounds.size.width, self.tableView.bounds.size.height))
        noDataLabel.text = "No Data Available"
        noDataLabel.textColor = UIColor(red: 22.0/255.0, green: 106.0/255.0, blue: 176.0/255.0, alpha: 1.0)
        noDataLabel.textAlignment = NSTextAlignment.Center
        self.tableView.backgroundView = noDataLabel

    }
    return numOfSection
}

Mas se você estiver carregando informações de um JSON, você precisa verificar se o JSON está vazio ou não, portanto, se você colocar um código como este, ele inicialmente mostra a mensagem "Sem dados" e depois desaparece. Porque depois que a tabela recarrega os dados a mensagem se esconde. Portanto, você pode colocar esse código para carregar dados JSON em uma matriz. TÃO :-

func numberOfSectionsInTableView(tableView: UITableView) -> Int {

    return 1
}

func extract_json(data:NSData) {


    var error: NSError?

    let jsonData: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers , error: &error)
    if (error == nil) {
        if let jobs_list = jsonData as? NSArray
        {
            if jobs_list.count == 0 {

                var noDataLabel: UILabel = UILabel(frame: CGRectMake(0, 0, self.tableView.bounds.size.width, self.tableView.bounds.size.height))
                noDataLabel.text = "No Jobs Available"
                noDataLabel.textColor = UIColor(red: 22.0/255.0, green: 106.0/255.0, blue: 176.0/255.0, alpha: 1.0)
                noDataLabel.textAlignment = NSTextAlignment.Center
                self.tableView.backgroundView = noDataLabel

            }

            for (var i = 0; i < jobs_list.count ; i++ )
            {
                if let jobs_obj = jobs_list[i] as? NSDictionary
                {
                    if let vacancy_title = jobs_obj["VacancyTitle"] as? String
                    {
                        CJobTitle.append(vacancy_title)

                        if let vacancy_job_type = jobs_obj["VacancyJobType"] as? String
                        {
                            CJobType.append(vacancy_job_type)

                            if let company_name = jobs_obj["EmployerCompanyName"] as? String
                            {
                                CCompany.append(company_name)

                                    if let company_logo_url = jobs_obj["EmployerCompanyLogo"] as? String
                                    {
                                        //CCompanyLogo.append("http://google.com" + company_logo_url)

                                        let url = NSURL(string: "http://google.com" + company_logo_url )
                                        let data = NSData(contentsOfURL:url!)
                                        if data != nil {
                                            CCompanyLogoImage.append(UIImage(data: data!)!)
                                        }

                                        if let vacancy_id = jobs_obj["VacancyID"] as? String
                                        {
                                            CVacancyId.append(vacancy_id)

                                        }

                                    }

                            }

                        }
                    }
                }
            }
        }
    }
    do_table_refresh();


}

func do_table_refresh() {

    dispatch_async(dispatch_get_main_queue(), {
        self.tableView.reloadData()
        return
    })
}

Isso funciona muito bem para exibir o rótulo quando não há dados nas linhas. No entanto, qual é a melhor maneira de lidar com quando os dados chegam e self.tableView.reloadData()são chamados? Descobri que ele está adicionando minhas novas linhas, mas noDataLabelainda é exibido abaixo delas.
tylerSF de

1
Se sua matriz tem item apenas defina self.tableView.backgroundView = nil
Chathuranga Silva

if jobs_list.count == 0 {// adicionar o código fornecido acima} else {self.tableView.backgroundView = nil}
Chathuranga Silva

perfeito. adicionar self.tableView.backgroundView = nilna minha declaração if antes de return jobs_list.count funcionar bem. obrigado
tylerSF de

Não use a primeira solução nesta resposta. Os métodos de fonte de dados de exibição de tabela nunca devem fazer mais do que deveriam. numberOfSectionsdeve retornar uma contagem e é isso. O mesmo para numberOfRowsInSection. Eles podem ser chamados várias vezes a qualquer momento. Nunca atualize visualizações ou dados, nem faça nada, exceto retornar uma contagem. A lógica para atualizar as visualizações nunca deve estar nesses métodos.
rmaddy

6

Você pode tentar este controle. É muito legal. DZNEmptyDataSet

Ou se eu fosse você tudo que faria é

  • Verifique se o seu array de dados está vazio
  • Se estiver vazio, adicione um objeto chamado @ "Sem Dados" a ele
  • Exibir essa string em cell.textLabel.text

Mole-mole


5

Swift 3 (atualizado):

override func numberOfSections(in tableView: UITableView) -> Int {
    if myArray.count > 0 {
        self.tableView.backgroundView = nil
        self.tableView.separatorStyle = .singleLine
        return 1
    }

    let rect = CGRect(x: 0,
                      y: 0,
                      width: self.tableView.bounds.size.width,
                      height: self.tableView.bounds.size.height)
    let noDataLabel: UILabel = UILabel(frame: rect)

    noDataLabel.text = "Custom message."
    noDataLabel.textColor = UIColor.white
    noDataLabel.textAlignment = NSTextAlignment.center
    self.tableView.backgroundView = noDataLabel
    self.tableView.separatorStyle = .none

    return 0
}

Não use esta solução. Os métodos de fonte de dados de exibição de tabela nunca devem fazer mais do que deveriam. numberOfSectionsdeve retornar uma contagem e é isso. O mesmo para numberOfRowsInSection. Eles podem ser chamados várias vezes a qualquer momento. Nunca atualize visualizações ou dados, nem faça nada, exceto retornar uma contagem. A lógica para atualizar as visualizações nunca deve estar nesses métodos.
rmaddy

Concordo. Esta solução pode ser melhorada, mas também pode ser usada.
Teodor Ciuraru

Como você pode concordar que não deve usar essa solução, mas afirmar que ela também pode ser usada? Isso é uma contradição.
rmaddy

Concordo que esta solução pode ser melhorada, mas, no estado atual, também funcionará.
Teodor Ciuraru

5

Swift3.0

Espero que sirva ao seu propósito ...... Em seu UITableViewController.

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if searchController.isActive && searchController.searchBar.text != "" {
        if filteredContacts.count > 0 {
            self.tableView.backgroundView = .none;
            return filteredContacts.count
        } else {
            Helper.EmptyMessage(message: ConstantMap.NO_CONTACT_FOUND, viewController: self)
            return 0
        }
    } else {
        if contacts.count > 0 {
            self.tableView.backgroundView = .none;
            return contacts.count
        } else {
            Helper.EmptyMessage(message: ConstantMap.NO_CONTACT_FOUND, viewController: self)
            return 0
        }
    }
}

Classe auxiliar com função:

 /* Description: This function generate alert dialog for empty message by passing message and
           associated viewcontroller for that function
           - Parameters:
            - message: message that require for  empty alert message
            - viewController: selected viewcontroller at that time
         */
        static func EmptyMessage(message:String, viewController:UITableViewController) {
            let messageLabel = UILabel(frame: CGRect(x: 0, y: 0, width: viewController.view.bounds.size.width, height: viewController.view.bounds.size.height))
            messageLabel.text = message
            let bubbleColor = UIColor(red: CGFloat(57)/255, green: CGFloat(81)/255, blue: CGFloat(104)/255, alpha :1)

            messageLabel.textColor = bubbleColor
            messageLabel.numberOfLines = 0;
            messageLabel.textAlignment = .center;
            messageLabel.font = UIFont(name: "TrebuchetMS", size: 18)
            messageLabel.sizeToFit()

            viewController.tableView.backgroundView = messageLabel;
            viewController.tableView.separatorStyle = .none;
        }

Não use esta solução. Os métodos de fonte de dados de exibição de tabela nunca devem fazer mais do que deveriam. numberOfSectionsdeve retornar uma contagem e é isso. O mesmo para numberOfRowsInSection. Eles podem ser chamados várias vezes a qualquer momento. Nunca atualize visualizações ou dados, nem faça nada, exceto retornar uma contagem. A lógica para atualizar as visualizações nunca deve estar nesses métodos.
rmaddy

3

Acho que a maneira mais elegante de resolver seu problema é mudar de a UITableViewControllerpara a UIViewControllerque contém a UITableView. Desta forma, você pode adicionar o UIViewque quiser como subvisões da visão principal.

Eu não recomendaria usar um UITableViewCell para fazer isso, você pode precisar adicionar coisas adicionais no futuro e as coisas podem ficar feias rapidamente.

Você também pode fazer algo assim, mas também não é a melhor solução.

UIWindow* window = [[UIApplication sharedApplication] keyWindow];
[window addSubview: OverlayView];

Obrigado pela cor em torno da qual é a forma mais elegante de implementar, sempre uma boa maneira de pensar sobre isso. Posso tentar mudar meu storyboard para usar um UIViewControllercontendo a UITableView.
SRMR

1
Essa é a maneira mais preparada para o futuro. Nunca usei um para UITableViewControllermim mesmo, porque usá-lo não é realmente muito mais fácil do que fazê-lo de outra forma, mas limita sua capacidade de mudar as coisas no futuro.
Cihan Tek

Isso não é compatível com o futuro se você tiver barras translúcidas. Eu recomendo fortemente contra. No mínimo, faça um UIViewController que contenha um UITableViewController e ajuste as coisas apropriadamente.
xtravar

3

Use este código em seu numberOfSectionsInTableViewmétodo: -

if ([array count]==0
{

    UILabel *fromLabel = [[UILabel alloc]initWithFrame:CGRectMake(50, self.view.frame.size.height/2, 300, 60)];                                                                                        
    fromLabel.text =@"No Result";
    fromLabel.baselineAdjustment = UIBaselineAdjustmentAlignBaselines;
    fromLabel.backgroundColor = [UIColor clearColor];
    fromLabel.textColor = [UIColor lightGrayColor];
    fromLabel.textAlignment = NSTextAlignmentLeft;
    [fromLabel setFont:[UIFont fontWithName:Embrima size:30.0f]];
    [self.view addSubview:fromLabel];
    [self.tblView setHidden:YES];
}

1
Não use esta solução. Os métodos de fonte de dados de exibição de tabela nunca devem fazer mais do que deveriam. numberOfSectionsdeve retornar uma contagem e é isso. O mesmo para numberOfRowsInSection. Eles podem ser chamados várias vezes a qualquer momento. Nunca atualize visualizações ou dados, nem faça nada, exceto retornar uma contagem. A lógica para atualizar as visualizações nunca deve estar nesses métodos.
rmaddy

2

SWIFT 3

        let noDataLabel: UILabel     = UILabel(frame: CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: tableView.bounds.size.height))
        noDataLabel.text             = "No data available"
        noDataLabel.textColor        = UIColor.white
        noDataLabel.font             = UIFont(name: "Open Sans", size: 15)
        noDataLabel.textAlignment    = .center
        tableView.backgroundView = noDataLabel
        tableView.separatorStyle = .none

2

Se você não usar o rodapé do tableview e não quiser que o tableview preencha a tela com células vazias da tabela padrão, sugiro que você defina o rodapé do tableview como um UIView vazio. Não sei a sintaxe correta para fazer isso em obj-c ou Swift, mas em Xamarin.iOS eu faria assim:

public class ViewController : UIViewController
{
    UITableView _table;

    public ViewController (IntPtr handle) : base (handle)
    {
    }

    public override void ViewWillAppear(bool animated) {
        // Initialize table

        _table.TableFooterView = new UIView();
    }
}

O código acima resultará em uma tableview sem as células vazias


2

Aqui está a solução que funcionou para mim.

  1. Adicione o seguinte código a um novo arquivo.

  2. Altere sua classe de tabela para a classe personalizada "MyTableView" de storyboard ou .xib

(isso funcionará apenas para a primeira seção. Se você quiser personalizar mais, faça alterações na função reloadData () MyTableView de acordo com as outras seções)

public class MyTableView: UITableView {

    override public func reloadData() {
        super.reloadData()

        if self.numberOfRows(inSection: 0) == 0 {
            if self.viewWithTag(1111) == nil {
                let noDataLabel = UILabel()
                noDataLabel.textAlignment = .center
                noDataLabel.text = "No Data Available"
                noDataLabel.tag = 1111
                noDataLabel.center = self.center
                self.backgroundView = noDataLabel
            }

        } else {
            if self.viewWithTag(1111) != nil {
                self.backgroundView = nil
            }
        }
    }
}

Esta é uma boa abordagem. Eu adicionei alguns aprimoramentos a seguir para torná-lo mais arredondado. 1. Cache separador de estilo de tableview e restaure-o na transição de estado vazio / não vazio para tornar esta subclasse aplicável para casos de uso em que diferentes estilos de separador são desejados. 2. Adicione @IBInspectable var emptyStateText: String?e marque esta classe, pois @IBDesignableentão você será capaz de alterar diferentes textos de estado vazio para diferentes cenas em storyboard ou xibs. Aproveitar! :)
Egist Li

1

Eu apresentaria uma visualização de sobreposição com a aparência e a mensagem que você deseja, se a visualização em mesa não tivesse resultados. Você poderia fazer isso em ViewDidAppear, então você tem os resultados antes de mostrar / não mostrar a vista.


1

Se você quiser fazer isso sem nenhum código, tente isso!

Clique em sua tableView.

TableView Screenshot

Altere o estilo de "simples" para "agrupado".

Captura de tela 2 das propriedades da visualização da tabela

Agora, quando você usa ....

tableView.backgroundView = INSERT SUA ETIQUETA OU EXIBIR

Não vai mostrar os separadores!


1

Adicione este código em um arquivo e altere o tipo de coleção para CustomCollectionView

import Foundation

class CustomCollectionView: UICollectionView {

  var emptyModel = EmptyMessageModel()
  var emptyView: EmptyMessageView?
  var showEmptyView: Bool = true

  override func reloadData() {
    super.reloadData()

    emptyView?.removeFromSuperview()
    self.backgroundView = nil

    if !showEmptyView {
      return
    }

    if numberOfSections < 1 {
      let rect = CGRect(x: 0,
                        y: 0,
                        width: self.bounds.size.width,
                        height: self.bounds.size.height)

      emptyView = EmptyMessageView()
      emptyView?.frame = rect
      if let emptyView = emptyView {
        //                self.addSubview(emptyView)
        self.backgroundView = emptyView
      }
      emptyView?.setView(with: emptyModel)

    } else {
      emptyView?.removeFromSuperview()
      self.backgroundView = nil
    }
  }
}

class EmptyMessageView: UIView {

  @IBOutlet weak var messageLabel: UILabel!
  @IBOutlet weak var imageView: UIImageView!

  var view: UIView!

  override init(frame: CGRect) {
    super.init(frame: frame)
    xibSetup()
  }

  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    xibSetup()
  }

  func xibSetup() {
    view = loadViewFromNib()

    view.frame = bounds

    view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    addSubview(view)
  }

  func loadViewFromNib() -> UIView {

    let bundle = Bundle(for: type(of: self))
    let nib = UINib(nibName: "EmptyMessageView", bundle: bundle)
    let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView

    return view
  }

  func setView(with model: EmptyMessageModel) {
    messageLabel.text = model.message ?? ""
    imageView.image = model.image ?? #imageLiteral(resourceName: "no_notification")
  }
}

///////////
class EmptyMessageModel {
  var message: String?
  var image: UIImage?

  init(message: String = "No data available", image: UIImage = #imageLiteral(resourceName: "no_notification")) {
    self.message = message
    self.image = image
  }
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.