diciembre 21, 2025
13 min de lectura

Preguntas para Entrevistas de Desarrollador Mobile Junior (iOS): Guía Completa

interview
career-advice
job-search
entry-level
Preguntas para Entrevistas de Desarrollador Mobile Junior (iOS): Guía Completa
Milad Bonakdar

Milad Bonakdar

Autor

Domina los fundamentos del desarrollo de iOS con preguntas esenciales para entrevistas que cubren Swift, UIKit, SwiftUI, persistencia de datos y la arquitectura de aplicaciones iOS para desarrolladores junior.


Introducción

El desarrollo para iOS se ha convertido en una de las habilidades más buscadas en el desarrollo de aplicaciones móviles. Con Swift como lenguaje principal y potentes frameworks como UIKit y SwiftUI, los desarrolladores de iOS crean experiencias para millones de usuarios en todo el mundo.

Esta guía cubre preguntas esenciales para entrevistas de Desarrolladores iOS Junior. Exploramos los fundamentos de Swift, el desarrollo de la interfaz de usuario, la persistencia de datos, las redes y las mejores prácticas de iOS para ayudarte a prepararte para tu primer puesto como desarrollador de iOS.


Fundamentos de Swift (6 Preguntas)

1. ¿Cuál es la diferencia entre var y let en Swift?

Respuesta:

  • var: Declara una variable mutable. Su valor se puede cambiar después de la inicialización.
  • let: Declara una constante inmutable. Una vez establecida, su valor no se puede cambiar.
  • Mejor práctica: Utiliza let por defecto para mayor seguridad y claridad. Solo usa var cuando sepas que el valor va a cambiar.
let name = "John"  // No se puede cambiar
var age = 25       // Se puede cambiar
age = 26           // Válido
// name = "Jane"   // Error: No se puede asignar al valor

Frecuencia: Muy Común Dificultad: Fácil


2. Explica los Optionals en Swift. ¿Qué es el Optional Binding?

Respuesta: Los Optionals representan un valor que podría ser nil (ausencia de valor).

  • Declaración: Usa ? después del tipo: var name: String?
  • Métodos de Desempaquetado:
    • Force Unwrapping: name! (peligroso, falla si es nil)
    • Optional Binding: Desempaqueta de forma segura usando if let o 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("No hay email")
}

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

Frecuencia: Muy Común Dificultad: Fácil


3. ¿Cuál es la diferencia entre una class y una struct en Swift?

Respuesta:

  • Class: Tipo de referencia (almacenado en el heap). Admite herencia. Se pasa por referencia.
  • Struct: Tipo de valor (almacenado en la pila). No hay herencia. Se pasa por copia.
  • Cuándo usar:
    • Struct: Para modelos de datos simples, cuando se desean semánticas de valor (copias independientes)
    • Class: Cuando se necesita herencia, semántica de referencia o desinicializadores
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  // Se crea una copia
p2.x = 10    // p1.x sigue siendo 0

var person1 = Person(name: "John")
var person2 = person1  // Misma referencia
person2.name = "Jane"  // person1.name también es "Jane"

Frecuencia: Muy Común Dificultad: Media


4. ¿Qué son los Closures en Swift?

Respuesta: Los Closures son bloques de funcionalidad autocontenidos que se pueden pasar y usar en tu código. Son similares a las lambdas o funciones anónimas en otros lenguajes.

  • Sintaxis: { (parámetros) -> TipoDeRetorno in sentencias }
  • Captura de Valores: Los Closures pueden capturar y almacenar referencias a variables de su contexto circundante.
  • Uso Común: Completion handlers, callbacks, operaciones de array.
// Closure simple
let greet = { (name: String) -> String in
    return "¡Hola, \(name)!"
}
print(greet("Alice"))

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

Frecuencia: Muy Común Dificultad: Media


5. Explica la diferencia entre referencias weak y unowned.

Respuesta: Ambas se utilizan para prevenir ciclos de retención (fugas de memoria) en tipos de referencia.

  • weak: Referencia opcional que automáticamente se convierte en nil cuando el objeto referenciado se desasigna. Úsala cuando la referencia pueda sobrevivir al objeto.
  • unowned: Referencia no opcional que asume que el objeto siempre existirá. Falla si se accede a ella después de la desasignación. Úsala cuando estés seguro de que la referencia no sobrevivirá al objeto.
class Person {
    var name: String
    weak var apartment: Apartment?  // weak para prevenir el ciclo de retención
    init(name: String) { self.name = name }
}

class Apartment {
    var unit: String
    unowned let tenant: Person  // unowned - el apartamento siempre tiene un inquilino
    init(unit: String, tenant: Person) {
        self.unit = unit
        self.tenant = tenant
    }
}

Frecuencia: Común Dificultad: Media


6. ¿Qué son los Protocolos en Swift?

Respuesta: Los protocolos definen un esquema de métodos, propiedades y otros requisitos que se adaptan a una tarea o funcionalidad particular. Las clases, structs y enums pueden adoptar protocolos.

  • Similar a: Interfaces en otros lenguajes
  • Extensiones de Protocolo: Pueden proporcionar implementaciones predeterminadas
  • Programación Orientada a Protocolos: El paradigma preferido de Swift
protocol Drawable {
    func draw()
}

struct Circle: Drawable {
    var radius: Double
    
    func draw() {
        print("Dibujando círculo con radio \(radius)")
    }
}

struct Rectangle: Drawable {
    var width: Double
    var height: Double
    
    func draw() {
        print("Dibujando rectángulo \(width)x\(height)")
    }
}

Frecuencia: Muy Común Dificultad: Fácil


Fundamentos de UIKit (5 Preguntas)

7. ¿Cuál es la diferencia entre UIView y UIViewController?

Respuesta:

  • UIView: Representa un área rectangular en la pantalla. Maneja el dibujo y el manejo de eventos. Ejemplos: UILabel, UIButton, UIImageView.
  • UIViewController: Gestiona una jerarquía de vistas. Maneja el ciclo de vida de la vista, las interacciones del usuario y la navegación. Contiene una vista raíz y gestiona sus subvistas.
  • Relación: Un controlador de vista gestiona vistas. Un controlador de vista puede tener muchas vistas.

Frecuencia: Muy Común Dificultad: Fácil


8. Explica los métodos del ciclo de vida del Controlador de Vista.

Respuesta: Los controladores de vista tienen métodos de ciclo de vida específicos que se llaman en orden:

  1. viewDidLoad(): Se llama una vez cuando la vista se carga en la memoria. Configuración que debe ocurrir una vez.
  2. viewWillAppear(_:): Se llama antes de que la vista aparezca en la pantalla. Se puede llamar varias veces.
  3. viewDidAppear(_:): Se llama después de que la vista aparece en la pantalla. Comienza las animaciones aquí.
  4. viewWillDisappear(_:): Se llama antes de que la vista desaparezca.
  5. viewDidDisappear(_:): Se llama después de que la vista desaparece. Limpia los recursos.
override func viewDidLoad() {
    super.viewDidLoad()
    // Configuración única: configurar la interfaz de usuario, cargar datos
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    // Actualizar datos, comenzar a escuchar notificaciones
}

Frecuencia: Muy Común Dificultad: Fácil


9. ¿Qué es Auto Layout y cómo usas las constraints?

Respuesta: Auto Layout es un sistema de diseño basado en constraints que te permite crear interfaces de usuario adaptables que funcionan en diferentes tamaños y orientaciones de pantalla.

  • Constraints: Definen las relaciones entre las vistas (ancho, alto, espacio, alineación)
  • Métodos:
    • Interface Builder: Editor visual en Xcode
    • Programático: API NSLayoutConstraint o NSLayoutAnchor
    • Visual Format Language: Basado en cadenas (menos común ahora)
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)
])

Frecuencia: Muy Común Dificultad: Media


10. ¿Cuál es la diferencia entre frame y bounds?

Respuesta:

  • frame: La ubicación y el tamaño de la vista en el sistema de coordenadas de su supervista. Se utiliza para posicionar la vista.
  • bounds: La ubicación y el tamaño de la vista en su propio sistema de coordenadas. El origen suele ser (0, 0). Se utiliza para dibujar contenido dentro de la vista.
  • Diferencia clave: frame es relativo al padre, bounds es relativo a sí mismo.
let view = UIView(frame: CGRect(x: 50, y: 100, width: 200, height: 150))
print(view.frame)   // (50, 100, 200, 150) - posición en la supervista
print(view.bounds)  // (0, 0, 200, 150) - propio sistema de coordenadas

Frecuencia: Común Dificultad: Media


11. ¿Cómo manejas la entrada del usuario desde un UITextField?

Respuesta: Existen múltiples enfoques:

  • Target-Action: Agregar target para el evento .editingChanged
  • Delegate: Conformar al protocolo UITextFieldDelegate
  • Combine: Usar publishers (enfoque moderno)
class ViewController: UIViewController, UITextFieldDelegate {
    let textField = UITextField()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Enfoque Delegate
        textField.delegate = self
        
        // Enfoque 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
    }
}

Frecuencia: Muy Común Dificultad: Fácil


Fundamentos de SwiftUI (4 Preguntas)

12. ¿Qué es SwiftUI y en qué se diferencia de UIKit?

Respuesta: SwiftUI es el framework de interfaz de usuario declarativo de Apple introducido en iOS 13.

  • UIKit: Imperativo (le dices al sistema cómo construir la interfaz de usuario paso a paso). Maduro, ampliamente utilizado.
  • SwiftUI: Declarativo (describes cómo debería ser la interfaz de usuario). Moderno, menos código, actualizaciones automáticas.
  • Características clave:
    • Vista previa en vivo en Xcode
    • Multiplataforma (iOS, macOS, watchOS, tvOS)
    • Actualizaciones de la interfaz de usuario basadas en el estado
    • Animaciones integradas
// SwiftUI
struct ContentView: View {
    @State private var count = 0
    
    var body: some View {
        VStack {
            Text("Conteo: \(count)")
            Button("Incrementar") {
                count += 1
            }
        }
    }
}

Frecuencia: Muy Común Dificultad: Fácil


13. Explica @State, @Binding y @ObservedObject en SwiftUI.

Respuesta: Estos son property wrappers para administrar el estado en SwiftUI:

  • @State: Estado privado propiedad de la vista. Cuando cambia, la vista se vuelve a renderizar.
  • @Binding: Crea una conexión bidireccional a una propiedad @State propiedad de una vista principal.
  • @ObservedObject: Hace referencia a un objeto externo (clase que se ajusta a ObservableObject). La vista se actualiza cuando cambian las propiedades @Published del objeto.
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)  // Pasar binding
            Text(userData.name)
        }
    }
}

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

Frecuencia: Común Dificultad: Media


14. ¿Cómo se crea una lista en SwiftUI?

Respuesta: Usa la vista List para mostrar colecciones de datos desplazables.

struct ContentView: View {
    let fruits = ["Manzana", "Plátano", "Naranja", "Uva"]
    
    var body: some View {
        List(fruits, id: \.self) { fruit in
            Text(fruit)
        }
    }
}

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

struct TaskListView: View {
    let tasks = [
        Task(title: "Comprar comestibles"),
        Task(title: "Pasear al perro")
    ]
    
    var body: some View {
        List(tasks) { task in
            Text(task.title)
        }
    }
}

Frecuencia: Común Dificultad: Fácil


15. ¿Qué son los Modificadores de Vista en SwiftUI?

Respuesta: Los modificadores de vista son métodos que crean una nueva vista con propiedades modificadas. Son encadenables.

  • Modificadores comunes: .padding(), .background(), .foregroundColor(), .font(), .frame()
  • El orden importa: Los modificadores se aplican en secuencia
Text("¡Hola, 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())
    }
}

Frecuencia: Común Dificultad: Fácil


Datos y Redes (5 Preguntas)

16. ¿Cómo realizas una solicitud de red en iOS?

Respuesta: Usa URLSession para tareas de red.

func fetchData() {
    guard let url = URL(string: "https://api.ejemplo.com/data") else { return }
    
    let task = URLSession.shared.dataTask(with: url) { data, response, error in
        if let error = error {
            print("Error: \(error)")
            return
        }
        
        guard let data = data else { return }
        
        // Analizar JSON
        do {
            let decoder = JSONDecoder()
            let result = try decoder.decode(MyModel.self, from: data)
            print(result)
        } catch {
            print("Error de decodificación: \(error)")
        }
    }
    
    task.resume()
}

Frecuencia: Muy Común Dificultad: Media


17. ¿Qué es Codable en Swift?

Respuesta: Codable es un alias de tipo para los protocolos Encodable & Decodable. Permite una fácil conversión entre tipos de Swift y representaciones externas como JSON.

  • Síntesis automática: Swift genera automáticamente código de codificación/decodificación si todas las propiedades son Codable.
  • Claves personalizadas: Usa el enum CodingKeys para mapear diferentes nombres de propiedad.
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 a JSON
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let jsonData = try encoder.encode(user)

Frecuencia: Muy Común Dificultad: Fácil


18. ¿Cómo persistes datos localmente en iOS?

Respuesta: Múltiples opciones para la persistencia de datos local:

  • UserDefaults: Almacenamiento simple de clave-valor para pequeñas cantidades de datos (configuraciones, preferencias)
  • Sistema de archivos: Guarda archivos en el directorio Documents o Cache
  • Core Data: El framework de Apple para la gestión y persistencia de gráficos de objetos
  • SQLite: Base de datos relacional
  • Keychain: Almacenamiento seguro para datos confidenciales (contraseñas, tokens)
// UserDefaults
UserDefaults.standard.set("John", forKey: "username")
let username = UserDefaults.standard.string(forKey: "username")

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

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

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

Frecuencia: Muy Común Dificultad: Fácil


19. ¿Cuál es la diferencia entre operaciones síncronas y asíncronas?

Respuesta:

  • Síncrono: Bloquea el hilo actual hasta que se completa la operación. Puede congelar la interfaz de usuario si se ejecuta en el hilo principal.
  • Asíncrono: No bloquea el hilo. La operación se ejecuta en segundo plano y se llama a un completion handler cuando termina.
  • Hilo principal: Las actualizaciones de la interfaz de usuario deben realizarse en el hilo principal. Usa DispatchQueue.main.async para cambiar al hilo principal.
// Síncrono (MALO para llamadas de red)
let data = try Data(contentsOf: url)  // Se bloquea hasta que se complete

// Asíncrono (BUENO)
URLSession.shared.dataTask(with: url) { data, response, error in
    // Esto se ejecuta en un hilo en segundo plano
    
    DispatchQueue.main.async {
        // Actualizar la interfaz de usuario en el hilo principal
        self.label.text = "Datos cargados"
    }
}.resume()

Frecuencia: Común Dificultad: Fácil


20. ¿Qué es Grand Central Dispatch (GCD)?

Respuesta: GCD es la API de bajo nivel de Apple para gestionar operaciones concurrentes.

  • Dispatch Queues: Colas FIFO que ejecutan tareas en serie o concurrentemente
  • Main Queue: Cola en serie para actualizaciones de la interfaz de usuario
  • Global Queues: Colas concurrentes con diferentes prioridades (background, utility, userInitiated)
// Ejecutar en un hilo en segundo plano
DispatchQueue.global(qos: .background).async {
    // Computación pesada
    let result = performExpensiveOperation()
    
    // Actualizar la interfaz de usuario en el hilo principal
    DispatchQueue.main.async {
        self.label.text = result
    }
}

// Retrasar la ejecución
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
    print("Ejecutado después de 2 segundos")
}

Frecuencia: Común Dificultad: Media

Newsletter subscription

Consejos de carrera semanales que realmente funcionan

Recibe las últimas ideas directamente en tu bandeja de entrada

Deja de Postularte. Comienza a Ser Contratado.

Transforma tu currículum en un imán de entrevistas con optimización impulsada por IA confiada por buscadores de empleo en todo el mundo.

Comienza gratis

Compartir esta publicación

Duplica tus Llamadas para Entrevistas

Los candidatos que adaptan sus currículums a la descripción del trabajo obtienen 2.5 veces más entrevistas. Usa nuestra IA para personalizar tu CV automáticamente para cada solicitud al instante.