Swiftcontroles de acesso em Swiftsegurança de códig em SwiftComo usar fileprivate e open no SwiftFormação iOS com Swift
Código mais seguro em Swift com controles de acesso

Rocketseat

A hora de investir em você é AGORA!
Um único investimento. Tudo que você precisa para evoluir na carreira!
Faaala, dev? Tudo pronto para dar mais um passo na sua jornada com Swift?
Sabe quando você está construindo algo incrível, mas começa a sentir que o código está virando uma daquelas gavetas de "coisas aleatórias"? Onde qualquer parte do seu app pode mexer em tudo, e você fica com aquele medinho de que uma mudança aqui quebre algo totalmente inesperado lá na frente? Pois é, organização e segurança são chaves!
É aí que entram os controles de acesso em Swift! Eles são como os seguranças superinteligentes do seu código, definindo quem pode entrar e o que pode fazer em cada parte do seu projeto. Parece complicado? Que nada!
Neste artigo direto ao ponto, vamos desvendar juntos esses "guardiões" do Swift. Você vai entender exatamente o que são, por que são essenciais e como usar cada nível de acesso para deixar seu código mais limpo, seguro e profissional.
Bora desvendar esses segredos e dar um boost nos seus projetos Swift?
O que são controles de acesso?
Imagine seu código como uma casa inteligente. Você não deixaria a porta da rua escancarada, nem daria a chave do seu cofre pessoal para qualquer visitante, certo? Controles de acesso funcionam de forma parecida: eles restringem o acesso a partes do seu código (classes, structs, métodos, propriedades) com base em onde esse código está sendo chamado.
É sobre visibilidade e permissão.
Por que isso é tão importante?
- Segurança: impede que partes do seu código sejam usadas ou modificadas de forma inadequada, evitando bugs e comportamentos inesperados.
- Organização: ajuda a definir interfaces claras. Você expõe apenas o necessário, escondendo a complexidade interna. Fica mais fácil entender como usar um componente sem precisar saber todos os seus segredos.
- Trabalho em equipe: em times, define limites claros. Cada um sabe o que pode usar do código do outro sem medo de quebrar a implementação interna.
- Manutenção: facilita na hora de refatorar ou melhorar uma parte do código. Se os detalhes internos estão escondidos, você pode mudá-los sem afetar quem usa a parte "pública" do seu componente.
Entendido o porquê? Agora, vamos conhecer os guardiões.
Os 5 guardiões do código Swift
Swift nos oferece cinco níveis de controle de acesso, do mais restrito ao mais aberto. Vamos conhecer cada um:
private
- Acesso: só pode ser acessado de dentro da mesma definição (classe, struct, enum) e de extensões dessa definição que estejam no mesmo arquivo.
- Uso típico: para detalhes de implementação super internos, variáveis auxiliares que só fazem sentido dentro daquele bloco específico. É o seu diário trancado na gaveta.
struct CofreDoMayk { private var combinacaoSecreta: String = "123456" // Só o Mayk aqui dentro sabe func tentarAbrir(senha: String) -> Bool { // Pode acessar combinacaoSecreta aqui dentro return senha == self.combinacaoSecreta } } let meuCofre = CofreDoMayk() // print(meuCofre.combinacaoSecreta) // ERRO! Não pode acessar de fora. print(meuCofre.tentarAbrir(senha: "123456")) // OK, usa o método público
fileprivate
- Acesso: pode ser acessado de qualquer lugar dentro do mesmo arquivo fonte (
.swift).
- Uso típico: quando uma funcionalidade precisa ser compartilhada entre diferentes classes ou structs, mas apenas dentro daquele arquivo específico. É uma conversa na sala de estar, só a família (o arquivo) ouve.
// Arquivo: UtilsDaIsabela.swift fileprivate func logInternoDoArquivo(mensagem: String) { print("[LOG ISABELA]: \(mensagem)") } class GerenciadorDeLogin { func logarUsuario(nome: String) { // ... lógica de login ... logInternoDoArquivo(mensagem: "Tentativa de login para: \(nome)") // OK, mesmo arquivo } } struct ValidadorDeSenha { func validar(senha: String) -> Bool { logInternoDoArquivo(mensagem: "Validando senha...") // OK, mesmo arquivo return senha.count > 6 } } // Em outro arquivo .swift, a função logInternoDoArquivo seria inacessível.
internal
- Acesso: pode ser acessado de qualquer lugar dentro do mesmo módulo (seu aplicativo ou framework).
- Uso típico: a grande maioria do código do seu aplicativo. Classes, funções e propriedades que precisam interagir entre si dentro do seu projeto, mas não precisam ser expostas para fora (caso você estivesse criando um framework).
// Não precisa escrever 'internal', é o padrão! class PerfilUsuario { var nome: String // internal por padrão var email: String // internal por padrão init(nome: String, email: String) { self.nome = nome self.email = email } func exibirBoasVindas() { // internal por padrão print("Boas-vindas, \(nome)!") } } // Em qualquer outro arquivo DENTRO do mesmo app/módulo: let perfilDaFernanda = PerfilUsuario(nome: "Fernanda", email: "fernanda@rocketseat.team") perfilDaFernanda.exibirBoasVindas() // OK print(perfilDaFernanda.nome) // OK
Este é o nível padrão! Se você não escrever nada (
private, public, etc.), o Swift assume que é internal.public
- Acesso: pode ser acessado de qualquer lugar, inclusive de fora do módulo (por exemplo, se outro app importar seu framework).
- Uso típico: para definir a interface pública de um framework ou biblioteca.
// Em um Framework "ComponentesDoRodrigo.framework" public class BotaoCustomizado { public var titulo: String = "Clique Aqui" public init() {} // O inicializador precisa ser public também! public func acaoDoClique() { print("Botão clicado!") } } // Em um App que importa "ComponentesDoRodrigo.framework": // let meuBotao = BotaoCustomizado() // OK // meuBotao.titulo = "Meu Botão" // OK // meuBotao.acaoDoClique() // OK // class MeuBotaoEspecial : BotaoCustomizado {} // ERRO! Não pode subclassificar public fora do módulo.
Entidades
public não podem ser subclassificadas (para classes) ou sobrescritas (para métodos) fora do módulo onde foram definidas. Pense como uma API: você pode usar, mas não pode alterar a estrutura fundamental dela por fora.open
- Acesso: o mais permissivo. Pode ser acessado de qualquer lugar, dentro ou fora do módulo.
- Uso típico: usado principalmente em frameworks que são projetados para serem extensíveis por quem os utiliza. Pense em classes base que outros devs podem querer herdar e customizar. Se você está apenas desenvolvendo seu app e não um framework, provavelmente nunca vai precisar usar
open
// Em um Framework "FrameworkBaseDoDiego.framework" open class ViewControllerBase { open var nomeDaTela: String = "Tela Genérica" open func viewDidAppear() { // Método aberto para ser sobrescrito print("\(nomeDaTela) apareceu!") } } // Em um App que importa "FrameworkBaseDoDiego.framework": class MinhaTelaPrincipal : ViewControllerBase { // OK! Pode subclassificar open. override func viewDidAppear() { // OK! Pode sobrescrever open. self.nomeDaTela = "Tela Principal do App" super.viewDidAppear() // Chama a implementação original print("Lógica adicional da minha tela!") } }
Classes
open podem ser subclassificadas fora do módulo, e métodos open podem ser sobrescritos fora do módulo.Ufa! Esses são os 5 níveis. Parece muito, mas a prática leva à perfeição!
Colocando em prática: gerenciando tarefas
Vamos ver um exemplo mais integrado, usando diferentes níveis para gerenciar tarefas:
// Arquivo: TarefaManager.swift // Função auxiliar só para este arquivo fileprivate func registrarLog(id: UUID, acao: String) { print("[\(Date())] Tarefa \(id): \(acao)") } public struct Tarefa { // Pública: pode ser usada em qualquer lugar do app public let id: UUID // Pública e imutável: todos veem, ninguém muda public var descricao: String // Pública e mutável: descrição pode ser editada public var concluida: Bool = false // Pública: status pode ser alterado internal let projetoAssociado: String // Interna: só código do módulo sabe o projeto private var notasSecretas: String = "" // Privada: só a struct Tarefa manipula // Inicializador público public init(descricao: String, projeto: String) { self.id = UUID() self.descricao = descricao self.projetoAssociado = projeto // Definido na criação registrarLog(id: self.id, acao: "Criada no projeto '\(projeto)' por Laís") // Usa func fileprivate } // Método público para marcar como concluída public mutating func marcarConcluida() { self.concluida = true registrarLog(id: self.id, acao: "Marcada como concluída") limparNotasSecretas() // Chama método privado } // Método público para adicionar notas (que ficam privadas) public mutating func adicionarNotaSecreta(_ nota: String) { self.notasSecretas += "\(nota)\n" registrarLog(id: self.id, acao: "Nota secreta adicionada") } // Método privado para limpar notas ao concluir private mutating func limparNotasSecretas() { self.notasSecretas = "" print("Notas secretas da tarefa \(id) limpas.") } } // Classe interna para gerenciar a lista de tarefas internal class GerenciadorDeTarefas { internal var tarefas: [Tarefa] = [] internal func adicionar(_ tarefa: Tarefa) { self.tarefas.append(tarefa) print("Gerenciador: Tarefa \(tarefa.id) adicionada.") // Poderia acessar tarefa.projetoAssociado aqui, pois é internal } // ... outros métodos internos para buscar, remover tarefas, etc. }
Analisando as escolhas
Tarefa(struct):publicporque queremos criar e usar tarefas em várias partes do nosso app (ex: na UI, na lógica de negócios).
id,descricao,concluida:publicporque são informações essenciais que outras partes do app precisam ler e, em alguns casos, modificar (descricao,concluida).idélet(constante) para garantir unicidade após a criação.
projetoAssociado:internaltalvez porque a associação com um projeto seja uma lógica gerenciada apenas dentro deste módulo de gerenciamento, não exposta diretamente para a UI, por exemplo.
notasSecretas:privateporque são detalhes internos da tarefa. A struct oferece um métodopublic(adicionarNotaSecreta) para interagir com elas de forma controlada. Ninguém de fora pode ler ou limpar as notas diretamente.
registrarLog(func):fileprivateporque é uma função auxiliar usada apenas pelas entidades (Tarefa,GerenciadorDeTarefas) definidas neste arquivoTarefaManager.swift.
limparNotasSecretas(método):privatepois é uma ação interna daTarefa, chamada apenas pelo métodomarcarConcluida.
GerenciadorDeTarefas(class):internal(padrão) porque toda a lógica de gerenciamento da lista de tarefas acontece dentro deste módulo. A UI, por exemplo, interagiria com ele, mas ele não é feito para ser usado por outro módulo/framework.
Viu como cada nível tem seu propósito para criar um sistema mais organizado e seguro?
Regra de ouro: qual nível escolher?
Na dúvida, siga o princípio do menor privilégio:
- Comece sempre com
private. É o mais seguro.
- Se precisar acessar de outra função ou classe no mesmo arquivo, mude para
fileprivate.
- Se precisar acessar de outros arquivos dentro do seu app/módulo, use
internal(ou simplesmente não coloque nada, já que é o padrão).
- Só use
publicouopense você estiver criando um framework ou biblioteca que será usado por outros módulos ou apps, e você precisa definir uma interface externa clara.
Para a vasta maioria do código que você escreverá para seus aplicativos iOS,internal,fileprivateeprivateserão seus melhores amigos!
E no universo iOS?
Dominar os controles de acesso é FUNDAMENTAL no desenvolvimento iOS! Por quê?
- Arquitetura limpa (MVVM, MVC, VIPER...): ajuda a separar as responsabilidades. Sua View não deve acessar detalhes privados do seu ViewModel ou Service. Controles de acesso ajudam a impor isso.
- Testabilidade: componentes com interfaces bem definidas (graças aos controles de acesso) são mais fáceis de testar isoladamente.
- Reutilização: facilita criar componentes reutilizáveis e seguros dentro do seu próprio app.
- Menos bugs: evita que uma tela altere um estado interno de outra parte do app sem querer, causando comportamentos bizarros.
O código mais robusto, mais fácil de manter e menos propenso a quebrar. Tudo o que a gente quer!
Conclusão
Parabéns! Você desvendou os segredos dos controles de acesso em Swift! Agora você sabe que
private, fileprivate, internal, public e open não são só palavras bonitas, mas ferramentas poderosas para:- Proteger seu código contra usos indevidos.
- Organizar melhor seus projetos.
- Facilitar a colaboração e a manutenção.
Dominar esses fundamentos do Swift é o primeiro passo para criar aplicativos iOS incríveis que impactam o mundo. É a base para construir interfaces fluidas, lógicas de negócio sólidas e experiências que encantam os usuários.
Se você quer acelerar sua jornada, ir do zero à App Store dominando não só Swift em profundidade, mas também Xcode, arquiteturas como MVVM, integração com back-end e todos os segredos para publicar seu app, a Formação iOS com Swift da Rocketseat foi feita sob medida para você! Lá, você terá um guia completo, passo a passo, para se tornar um desenvolvedor iOS de destaque no mercado.
Nunca pare de estudar e codar! O universo da programação é vasto e cheio de possibilidades. Continue explorando, construindo e, claro, controlando o acesso ao seu código como um mestre!
A hora de investir em você é AGORA!
Um único investimento. Tudo que você precisa para evoluir na carreira!
Artigos_
Explore conteúdos relacionados
Descubra mais artigos que complementam seu aprendizado e expandem seu conhecimento.
