dezembro 21, 2025
12 min de leitura

Perguntas para Entrevista de Desenvolvedor Mobile Júnior (iOS): Guia Completo

interview
career-advice
job-search
entry-level
Perguntas para Entrevista de Desenvolvedor Mobile Júnior (iOS): Guia Completo
Milad Bonakdar

Milad Bonakdar

Autor

Domine os fundamentos do desenvolvimento iOS com perguntas essenciais para entrevistas, abrangendo Swift, UIKit, SwiftUI, persistência de dados e arquitetura de aplicativos iOS para desenvolvedores juniores.


Introdução

O desenvolvimento para iOS se tornou uma das habilidades mais procuradas no desenvolvimento de aplicativos móveis. Com Swift como linguagem principal e frameworks poderosos como UIKit e SwiftUI, os desenvolvedores iOS criam experiências para milhões de usuários em todo o mundo.

Este guia cobre perguntas essenciais para entrevistas de Desenvolvedores iOS Juniores. Exploramos os fundamentos do Swift, desenvolvimento de UI, persistência de dados, networking e as melhores práticas de iOS para ajudá-lo a se preparar para sua primeira função como desenvolvedor iOS.


Fundamentos de Swift (6 Perguntas)

1. Qual é a diferença entre var e let em Swift?

Resposta:

  • var: Declara uma variável mutável. Seu valor pode ser alterado após a inicialização.
  • let: Declara uma constante imutável. Uma vez definido, seu valor não pode ser alterado.
  • Melhor Prática: Use let por padrão para segurança e clareza. Use var somente quando souber que o valor será alterado.
let name = "John"  // Não pode ser alterado
var age = 25       // Pode ser alterado
age = 26           // Válido
// name = "Jane"   // Erro: Não pode atribuir ao valor

Raridade: Muito Comum Dificuldade: Fácil


2. Explique Optionals em Swift. O que é Optional Binding?

Resposta: Optionals representam um valor que pode ser nil (ausência de um valor).

  • Declaração: Use ? após o tipo: var name: String?
  • Métodos de Unwrapping:
    • Force Unwrapping: name! (perigoso, causa crash se for nil)
    • Optional Binding: Desembrulha com segurança usando if let ou guard let
    • Nil Coalescing: name ?? "Default"
    • Optional Chaining: user?.address?.city
var email: String? = "[email protected]"

// Optional Binding
if let unwrappedEmail = email {
    print("Email: \(unwrappedEmail)")
} else {
    print("Sem email")
}

// Guard statement
guard let email = email else { return }
print(email)

Raridade: Muito Comum Dificuldade: Fácil


3. Qual é a diferença entre uma class e uma struct em Swift?

Resposta:

  • Class: Tipo de referência (armazenado no heap). Suporta herança. Passado por referência.
  • Struct: Tipo de valor (armazenado na stack). Sem herança. Passado por cópia.
  • Quando usar:
    • Struct: Para modelos de dados simples, quando você deseja semântica de valor (cópias independentes)
    • Class: Quando você precisa de herança, semântica de referência ou deinitializers
struct Point {
    var x: Int
    var y: Int
}

class Person {
    var name: String
    init(name: String) { self.name = name }
}

var p1 = Point(x: 0, y: 0)
var p2 = p1  // Cópia criada
p2.x = 10    // p1.x ainda é 0

var person1 = Person(name: "John")
var person2 = person1  // Mesma referência
person2.name = "Jane"  // person1.name também é "Jane"

Raridade: Muito Comum Dificuldade: Média


4. O que são Closures em Swift?

Resposta: Closures são blocos de funcionalidade autocontidos que podem ser passados e usados ​​em seu código. Eles são semelhantes a lambdas ou funções anônimas em outras linguagens.

  • Sintaxe: { (parâmetros) -> ReturnType in statements }
  • Capturando Valores: Closures podem capturar e armazenar referências a variáveis ​​de seu contexto circundante.
  • Uso Comum: Completion handlers, callbacks, operações de array.
// Closure simples
let greet = { (name: String) -> String in
    return "Olá, \(name)!"
}
print(greet("Alice"))

// Sintaxe de trailing closure
let numbers = [1, 2, 3, 4, 5]
let doubled = numbers.map { $0 * 2 }
print(doubled)  // [2, 4, 6, 8, 10]

Raridade: Muito Comum Dificuldade: Média


5. Explique a diferença entre referências weak e unowned.

Resposta: Ambos são usados ​​para evitar ciclos de retenção (vazamentos de memória) em tipos de referência.

  • weak: Referência opcional que automaticamente se torna nil quando o objeto referenciado é desalocado. Use quando a referência pode sobreviver ao objeto.
  • unowned: Referência não opcional que assume que o objeto sempre existirá. Causa crash se acessado após a desalocação. Use quando tiver certeza de que a referência não sobreviverá ao objeto.
class Person {
    var name: String
    weak var apartment: Apartment?  // weak para evitar ciclo de retenção
    init(name: String) { self.name = name }
}

class Apartment {
    var unit: String
    unowned let tenant: Person  // unowned - apartamento sempre tem inquilino
    init(unit: String, tenant: Person) {
        self.unit = unit
        self.tenant = tenant
    }
}

Raridade: Comum Dificuldade: Média


6. O que são Protocols em Swift?

Resposta: Protocols definem um blueprint de métodos, propriedades e outros requisitos que se adequam a uma determinada tarefa ou funcionalidade. Classes, structs e enums podem adotar protocols.

  • Semelhante a: Interfaces em outras linguagens
  • Protocol Extensions: Podem fornecer implementações padrão
  • Programação Orientada a Protocolos: Paradigma preferido do Swift
protocol Drawable {
    func draw()
}

struct Circle: Drawable {
    var radius: Double
    
    func draw() {
        print("Desenhando círculo com raio \(radius)")
    }
}

struct Rectangle: Drawable {
    var width: Double
    var height: Double
    
    func draw() {
        print("Desenhando retângulo \(width)x\(height)")
    }
}

Raridade: Muito Comum Dificuldade: Fácil


Fundamentos de UIKit (5 Perguntas)

7. Qual é a diferença entre UIView e UIViewController?

Resposta:

  • UIView: Representa uma área retangular na tela. Lida com desenho e tratamento de eventos. Exemplos: UILabel, UIButton, UIImageView.
  • UIViewController: Gerencia uma hierarquia de visualizações. Lida com o ciclo de vida da visualização, interações do usuário e navegação. Contém uma view raiz e gerencia suas subviews.
  • Relacionamento: Um view controller gerencia views. Um view controller pode ter muitas views.

Raridade: Muito Comum Dificuldade: Fácil


8. Explique os métodos do ciclo de vida do View Controller.

Resposta: Os view controllers têm métodos de ciclo de vida específicos chamados em ordem:

  1. viewDidLoad(): Chamado uma vez quando a view é carregada na memória. Configuração que precisa acontecer uma vez.
  2. viewWillAppear(_:): Chamado antes da view aparecer na tela. Pode ser chamado várias vezes.
  3. viewDidAppear(_:): Chamado depois que a view aparece na tela. Inicie animações aqui.
  4. viewWillDisappear(_:): Chamado antes da view desaparecer.
  5. viewDidDisappear(_:): Chamado depois que a view desaparece. Limpe os recursos.
override func viewDidLoad() {
    super.viewDidLoad()
    // Configuração única: configure a UI, carregue os dados
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    // Atualize os dados, comece a ouvir as notificações
}

Raridade: Muito Comum Dificuldade: Fácil


9. O que é Auto Layout e como você usa constraints?

Resposta: Auto Layout é um sistema de layout baseado em constraints que permite criar UIs adaptáveis ​​que funcionam em diferentes tamanhos e orientações de tela.

  • Constraints: Definem relacionamentos entre views (largura, altura, espaçamento, alinhamento)
  • Métodos:
    • Interface Builder: Editor visual no Xcode
    • Programático: API NSLayoutConstraint ou NSLayoutAnchor
    • Visual Format Language: Baseado em string (menos comum agora)
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(button)

NSLayoutConstraint.activate([
    button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
    button.centerYAnchor.constraint(equalTo: view.centerYAnchor),
    button.widthAnchor.constraint(equalToConstant: 200),
    button.heightAnchor.constraint(equalToConstant: 50)
])

Raridade: Muito Comum Dificuldade: Média


10. Qual é a diferença entre frame e bounds?

Resposta:

  • frame: A localização e o tamanho da view no sistema de coordenadas de sua superview. Usado para posicionar a view.
  • bounds: A localização e o tamanho da view em seu próprio sistema de coordenadas. A origem é geralmente (0, 0). Usado para desenhar conteúdo dentro da view.
  • Diferença Principal: frame é relativo ao pai, bounds é relativo a si mesmo.
let view = UIView(frame: CGRect(x: 50, y: 100, width: 200, height: 150))
print(view.frame)   // (50, 100, 200, 150) - posição na superview
print(view.bounds)  // (0, 0, 200, 150) - próprio sistema de coordenadas

Raridade: Comum Dificuldade: Média


11. Como você lida com a entrada do usuário de um UITextField?

Resposta: Existem várias abordagens:

  • Target-Action: Adicione target para o evento .editingChanged
  • Delegate: Esteja em conformidade com o protocolo UITextFieldDelegate
  • Combine: Use publishers (abordagem moderna)
class ViewController: UIViewController, UITextFieldDelegate {
    let textField = UITextField()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Abordagem Delegate
        textField.delegate = self
        
        // Abordagem Target-Action
        textField.addTarget(self, action: #selector(textChanged), for: .editingChanged)
    }
    
    @objc func textChanged(_ textField: UITextField) {
        print("Texto: \(textField.text ?? "")")
    }
    
    // Método Delegate
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }
}

Raridade: Muito Comum Dificuldade: Fácil


Fundamentos de SwiftUI (4 Perguntas)

12. O que é SwiftUI e como é diferente do UIKit?

Resposta: SwiftUI é o framework de UI declarativo da Apple introduzido no iOS 13.

  • UIKit: Imperativo (você diz ao sistema como construir a UI passo a passo). Maduro, amplamente utilizado.
  • SwiftUI: Declarativo (você descreve como a UI deve ser). Moderno, menos código, atualizações automáticas.
  • Características Principais:
    • Visualização ao vivo no Xcode
    • Multiplataforma (iOS, macOS, watchOS, tvOS)
    • Atualizações de UI orientadas ao estado
    • Animações integradas
// SwiftUI
struct ContentView: View {
    @State private var count = 0
    
    var body: some View {
        VStack {
            Text("Contagem: \(count)")
            Button("Incrementar") {
                count += 1
            }
        }
    }
}

Raridade: Muito Comum Dificuldade: Fácil


13. Explique @State, @Binding e @ObservedObject em SwiftUI.

Resposta: Estes são property wrappers para gerenciar o estado no SwiftUI:

  • @State: Estado privado pertencente à view. Quando ele muda, a view é renderizada novamente.
  • @Binding: Cria uma conexão bidirecional com uma propriedade @State pertencente a uma view pai.
  • @ObservedObject: Referencia um objeto externo (classe em conformidade com ObservableObject). A view é atualizada quando as propriedades @Published do objeto são alteradas.
class UserData: ObservableObject {
    @Published var name = ""
}

struct ParentView: View {
    @State private var isOn = false
    @ObservedObject var userData = UserData()
    
    var body: some View {
        VStack {
            ChildView(isOn: $isOn)  // Passa binding
            Text(userData.name)
        }
    }
}

struct ChildView: View {
    @Binding var isOn: Bool  // Recebe binding
    
    var body: some View {
        Toggle("Switch", isOn: $isOn)
    }
}

Raridade: Comum Dificuldade: Média


14. Como você cria uma lista em SwiftUI?

Resposta: Use a view List para exibir coleções de dados roláveis.

struct ContentView: View {
    let fruits = ["Apple", "Banana", "Orange", "Grape"]
    
    var body: some View {
        List(fruits, id: \.self) { fruit in
            Text(fruit)
        }
    }
}

// Com modelo personalizado
struct Task: Identifiable {
    let id = UUID()
    let title: String
}

struct TaskListView: View {
    let tasks = [
        Task(title: "Comprar mantimentos"),
        Task(title: "Passear com o cachorro")
    ]
    
    var body: some View {
        List(tasks) { task in
            Text(task.title)
        }
    }
}

Raridade: Comum Dificuldade: Fácil


15. O que são View Modifiers em SwiftUI?

Resposta: View modifiers são métodos que criam uma nova view com propriedades modificadas. Eles são encadeáveis.

  • Modificadores Comuns: .padding(), .background(), .foregroundColor(), .font(), .frame()
  • Ordem Importa: Os modificadores são aplicados em sequência
Text("Olá, Mundo!")
    .font(.title)
    .foregroundColor(.blue)
    .padding()
    .background(Color.yellow)
    .cornerRadius(10)
    .shadow(radius: 5)

// Modificador personalizado
struct PrimaryButtonStyle: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding()
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(8)
    }
}

extension View {
    func primaryButton() -> some View {
        modifier(PrimaryButtonStyle())
    }
}

Raridade: Comum Dificuldade: Fácil


Dados e Networking (5 Perguntas)

16. Como você faz uma solicitação de rede no iOS?

Resposta: Use URLSession para tarefas de networking.

func fetchData() {
    guard let url = URL(string: "https://api.example.com/data") else { return }
    
    let task = URLSession.shared.dataTask(with: url) { data, response, error in
        if let error = error {
            print("Erro: \(error)")
            return
        }
        
        guard let data = data else { return }
        
        // Analisar JSON
        do {
            let decoder = JSONDecoder()
            let result = try decoder.decode(MyModel.self, from: data)
            print(result)
        } catch {
            print("Erro de decodificação: \(error)")
        }
    }
    
    task.resume()
}

Raridade: Muito Comum Dificuldade: Média


17. O que é Codable em Swift?

Resposta: Codable é um alias de tipo para os protocolos Encodable & Decodable. Ele permite a conversão fácil entre tipos Swift e representações externas como JSON.

  • Síntese Automática: Swift gera automaticamente o código de codificação/decodificação se todas as propriedades forem Codable.
  • Chaves Personalizadas: Use o enum CodingKeys para mapear diferentes nomes de propriedades.
struct User: Codable {
    let id: Int
    let name: String
    let email: String
}

// Decodificando JSON
let json = """
{
    "id": 1,
    "name": "John Doe",
    "email": "[email protected]"
}
""".data(using: .utf8)!

let decoder = JSONDecoder()
let user = try decoder.decode(User.self, from: json)

// Codificando para JSON
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let jsonData = try encoder.encode(user)

Raridade: Muito Comum Dificuldade: Fácil


18. Como você persiste dados localmente no iOS?

Resposta: Várias opções para persistência de dados local:

  • UserDefaults: Armazenamento simples de chave-valor para pequenas quantidades de dados (configurações, preferências)
  • File System: Salve arquivos no diretório Documents ou Cache
  • Core Data: O framework da Apple para gerenciamento e persistência de gráficos de objetos
  • SQLite: Banco de dados relacional
  • Keychain: Armazenamento seguro para dados confidenciais (senhas, tokens)
// UserDefaults
UserDefaults.standard.set("John", forKey: "username")
let username = UserDefaults.standard.string(forKey: "username")

// File System
let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let filePath = documentsPath.appendingPathComponent("data.json")

// Escrever
try data.write(to: filePath)

// Ler
let loadedData = try Data(contentsOf: filePath)

Raridade: Muito Comum Dificuldade: Fácil


19. Qual é a diferença entre operações síncronas e assíncronas?

Resposta:

  • Síncrono: Bloqueia a thread atual até que a operação seja concluída. Pode congelar a UI se executado na thread principal.
  • Assíncrono: Não bloqueia a thread. A operação é executada em segundo plano e um completion handler é chamado quando concluído.
  • Main Thread: As atualizações da UI devem acontecer na thread principal. Use DispatchQueue.main.async para mudar para a thread principal.
// Síncrono (RUIM para chamadas de rede)
let data = try Data(contentsOf: url)  // Bloqueia até a conclusão

// Assíncrono (BOM)
URLSession.shared.dataTask(with: url) { data, response, error in
    // Isso é executado na thread em segundo plano
    
    DispatchQueue.main.async {
        // Atualize a UI na thread principal
        self.label.text = "Dados carregados"
    }
}.resume()

Raridade: Comum Dificuldade: Fácil


20. O que é Grand Central Dispatch (GCD)?

Resposta: GCD é a API de baixo nível da Apple para gerenciar operações simultâneas.

  • Dispatch Queues: Filas FIFO que executam tarefas serialmente ou simultaneamente
  • Main Queue: Fila serial para atualizações da UI
  • Global Queues: Filas simultâneas com diferentes prioridades (background, utility, userInitiated)
// Executar na thread em segundo plano
DispatchQueue.global(qos: .background).async {
    // Computação pesada
    let result = performExpensiveOperation()
    
    // Atualize a UI na thread principal
    DispatchQueue.main.async {
        self.label.text = result
    }
}

// Atrasar a execução
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
    print("Executado após 2 segundos")
}

Raridade: Comum Dificuldade: Média


Newsletter subscription

Dicas de carreira semanais que realmente funcionam

Receba as últimas ideias diretamente na sua caixa de entrada

Crie um Currículo que Te Contrate 60% Mais Rápido

Em minutos, crie um currículo personalizado e compatível com ATS comprovado para conseguir 6 vezes mais entrevistas.

Crie um currículo melhor

Compartilhar esta publicação

Supere a Taxa de Rejeição de 75% do ATS

3 em cada 4 currículos nunca chegam a um olho humano. Nossa otimização de palavras-chave aumenta sua taxa de aprovação em até 80%, garantindo que os recrutadores realmente vejam seu potencial.