So meistern Sie das Swift-Vorstellungsgespräch: Top-Fragen für Fortgeschrittene
Ein Vorstellungsgespräch für eine iOS-Entwicklerposition ist nicht nur eine Überprüfung der Kenntnisse von UIKit und SwiftUI. Auf fortgeschrittenem Niveau möchten Personalverantwortliche und technische Leiter sicherstellen, dass Sie verstehen, wie der Speicher funktioniert, was class von struct im Kontext des Reference Counting unterscheidet, wie man eine Architektur mit Protokollen richtig aufbaut und wie man Asynchronität verwaltet. In diesem Artikel analysieren wir die wichtigsten Themen, die häufig in Swift-Vorstellungsgesprächen auf Middle- und Senior-Niveau vorkommen.
1. Speicherverwaltung und ARC (Automatic Reference Counting)
ARC ist eines der häufigsten Themen in Vorstellungsgesprächen. Sie müssen nicht nur die Theorie kennen, sondern auch erklären können, wie man Speicherlecks vermeidet.
1.1. Wie funktioniert ARC und welche Zyklen starker Referenzen gibt es?
ARC zählt automatisch die Anzahl der starken Referenzen auf ein Klassenobjekt. Sobald der Zähler Null erreicht, wird das Objekt aus dem Speicher entfernt. Ein Problem entsteht, wenn zwei Objekte stark aufeinander verweisen – es entsteht ein Zyklus (Retain Cycle).
class Parent { var child: Child?}
class Child { var parent: Parent? // starke Referenz zurück}
var parent: Parent? = Parent()var child: Child? = Child()parent?.child = childchild?.parent = parent// Beide Objekte werden niemals freigegeben1.2. Wie bricht man den Zyklus?
Verwenden Sie weak oder unowned. weak ist eine optionale Referenz, die automatisch nil wird, wenn das Objekt gelöscht wird. unowned ist nicht optional, geht aber davon aus, dass das Objekt mindestens so lange lebt wie das referenzierende Objekt.
class Child { weak var parent: Parent? // schwache Referenz}1.3. Wie funktioniert ARC mit Closures?
Closures erfassen externe Variablen. Wenn ein Closure als Eigenschaft einer Klasse gespeichert wird und darin self verwendet wird, entsteht ein Zyklus. Die Lösung ist die Verwendung von [weak self] oder [unowned self].
class NetworkManager { var completionHandler: (() -> Void)? func fetchData() { completionHandler = { [weak self] in guard let self = self else { return } self.processData() } } func processData() { }}2. Closures und escaping vs non-escaping
Das Verständnis des Unterschieds zwischen escaping und non-escaping Closures ist ein Muss für jede fortgeschrittene Position.
2.1. Was ist ein escaping Closure?
Ein Closure wird als escaping bezeichnet, wenn es nach der Rückkehr aus der Funktion aufgerufen werden kann. Standardmäßig sind alle Closures non-escaping – der Compiler weiß, dass sie innerhalb des Funktionskörpers ausgeführt werden. Für asynchrone Operationen (z. B. Netzwerkanfragen) muss explizit @escaping angegeben werden.
func performAsyncTask(completion: @escaping (String) -> Void) { DispatchQueue.global().async { // Simulation einer langen Aufgabe sleep(2) completion("Fertig") }}2.2. Warum sind non-escaping Closures schneller?
Der Compiler optimiert non-escaping Closures – er kann sie auf dem Stack speichern, anstatt sie auf dem Heap zu kopieren. Außerdem kann er die Referenzzählung vermeiden, da die Lebensdauer des Closures auf den Funktionsaufruf beschränkt ist.
3. Generics und Protokolle mit assoziierten Typen (PAT)
Generics sind die Grundlage von Swift. In einem Vorstellungsgespräch könnten Sie gebeten werden, eine generische Struktur zu schreiben oder zu erklären, wie Protokolle mit assoziierten Typen funktionieren.
3.1. Schreiben Sie eine generische Warteschlange (Queue)
struct Queue<T> { private var elements: [T] = [] mutating func enqueue(_ value: T) { elements.append(value) } mutating func dequeue() -> T? { guard !elements.isEmpty else { return nil }