Refactoring von Legacy-Code in Swift: Schritt-für-Schritt-Anleitung für iOS/macOS

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einleitung: Warum Legacy-Code in Swift ein Refactoring benötigt

Die Arbeit mit Legacy-Code ist ein unvermeidlicher Teil des Lebens eines iOS/macOS-Entwicklers. Selbst wenn ein Projekt ursprünglich in Swift geschrieben wurde, sammelt es im Laufe der Zeit technische Schulden an: veraltete Patterns, fehlende Tests, monolithische Architektur und die Vermischung von Swift mit Objective-C. Das Refactoring solchen Codes verbessert nicht nur die Lesbarkeit – es senkt die Wartungskosten, beschleunigt das Hinzufügen neuer Features und reduziert die Anzahl der Bugs.

In diesem Artikel werden wir konkrete Refactoring-Techniken für Legacy-Swift-Code durchgehen: von der Beseitigung von Force Unwrapping bis zur Migration von MVC zu MVVM. Alle Beispiele können sowohl für iOS- als auch für macOS-Projekte angewendet werden.



1. Bewertung und Vorbereitung: Wo man mit dem Refactoring beginnt

Bevor man Code ändert, ist es wichtig, seinen aktuellen Zustand zu verstehen. Nutzen Sie die integrierten Tools von Xcode und Metriken.



1.1. Analyse von Warnungen und Fehlern

Öffnen Sie das Projekt in Xcode und gehen Sie zum Report Navigator (Cmd+9). Achten Sie auf:

  • Gelbe Warnungen – veraltete APIs (deprecated), ungenutzte Variablen.
  • Rote Fehler – Syntaxfehler, die eine Folge einer unvollständigen Swift-Migration sein können.
  • SwiftLint/SwiftFormat – Schließen Sie einen Linter an, um automatisch Verstöße gegen den Code Style zu erkennen.


1.2. Suche nach "roten Flaggen" im Code

Durchsuchen Sie das Projekt mit der Suche (Cmd+Shift+F) nach folgenden Patterns:

  • ! – Force Unwrapping (optionale Werte, die die App zum Absturz bringen).
  • as! – Force Casting (Typumwandlung ohne Prüfung).
  • try! – Ignorieren von Fehlern.
  • NSObject – Vererbung von NSObject ohne Notwendigkeit (reines Swift erfordert dies nicht).
  • #selector – String-Selektoren, die besser durch #selector mit Typ ersetzt werden sollten.


// Schlecht (Legacy)let name = user.name!  // force unwrap — Absturz bei nil

// Gut (Refactoring)guard let name = user.name else { return}


1.3. Schreiben von Tests vor den Änderungen

Refactoring ohne Tests ist ein Risiko. Wenn es keine Tests gibt, beginnen Sie damit, sie für kritische Module hinzuzufügen. Verwenden Sie XCTest für Unit-Tests und XCUITest für UI.

Beispiel eines einfachen Tests für eine Legacy-Funktion:

class LegacyCalculatorTests: XCTestCase {    func testCalculateTotal() {        let calculator = LegacyCalculator()        let result = calculator.calculateTotal(items: [10, 20, 30])        XCTAssertEqual(result, 60)    }}


2. Grundlegende Techniken des Refactorings von Swift-Code

Kommen wir zu den praktischen Schritten, die Sie sofort anwenden können.



2.1. Ersetzen von Force Unwrapping durch sichere Patterns

Das häufigste Problem in Legacy-Code ist die allgegenwärtige Verwendung von !. Ersetzen Sie sie durch guard let, if let oder ?? (nil-coalescing).

// Vor dem Refactoringfunc getUserName() -> String {    return user.name!}

// Nach dem Refactoringfunc getUserName() -> String { return user.name ?? "Unknown"}


2.2. Beseitigung von Massive View Controller (MVC → MVVM)

Legacy-Projekte leiden oft unter "fetten" Controllern. Lagern Sie die Geschäftslogik in separate Services oder ViewModels aus.

// Legacy ViewController (Ausschnitt)class ProfileViewController: UIViewController {    @IBOutlet weak var nameLabel: UILabel!        override func viewDidLoad() {        super.viewDidLoad()        // Geschäftslogik direkt im Controller        let user = DataManager.shared.fetchUser()        nameLabel.text = user.name?.capitalized    }}

// Nach dem Refactoringclass ProfileViewModel { private let userService: UserService var userName: String { return userService.currentUs

Blogs

Buchempfehlungen