Migration des Objective-C-Frameworks zu Swift

Jul 29, 2021


Bevor Sie mit der Konvertierung von Objective-C-Code nach Swift beginnen, müssen Sie sich fragen, ob es sich lohnt. Warum wollen Sie es tun?

Für uns war es einfach: Wir wollten ein Framework haben, das vollständig mit Swift kompatibel ist, neue Muster und Funktionen nutzen, die es nur in Swift gibt, einfacher zu lesen und zu warten sein und eine moderne Codebasis für neue Entwickler im Team haben.

Ich dachte, dass der Prozess ziemlich einfach sein würde, aber ich habe mich geirrt. Ich sah mich mit vielen Herausforderungen konfrontiert, die ich beschreiben werde, um Ihnen zu helfen, wenn Sie sich entscheiden, mit diesem Projekt zu beginnen (und auch, um eine Referenz für mich selbst zu haben, falls ich es noch einmal tun muss).

Fangen wir also an!

Schritt 1 - Modernisieren Sie Ihren Objective-C-Code

Stellen Sie zuallererst sicher, dass jede neue Datei, die Sie erstellen, wenn möglich in Swift ist. Wenn nicht, modernisieren Sie Ihren Objective-C-Code. Hier sind einige Beispiele:

  • Anstelle von id als Rückgabetyp verwendet Ihre Klasse instancetype, was die Typsicherheit verbessert.
  • Verwenden Sie gegebenenfalls Eigenschaften anstelle von Instanzvariablen. Wenn Sie Eigenschaften erstellen, erhalten Sie standardmäßig automatisch Getter- und Setter-Methoden, außerdem haben Sie Zugriff auf Eigenschaftsattribute wie: weak, assign, retain usw.
  • Ändern Sie enum in NS_ENUM. Dies verbessert den Code-Wettbewerb in Xcode und gibt den Typ und die Größe Ihrer enums an.

Dies wird von Apple empfohlen und Sie können mehr Details darüber auf dieser Dokumentationsseite lesen.

Schritt 2 - Importieren von Swift-Code in ObjC

Migrating_Objective_C_Framework_to_Swift_2.webp

Um Swift-Code in Objective-C zu importieren, benötigen Sie zunächst einen Objective-C-Bridging-Header. Dieser wird von Xcode automatisch generiert, wenn Sie Swift-Dateien erstellen oder in Ihr Projekt einfügen.

Wenn Sie keinen Überbrückungsheader haben, können Sie ihn ganz einfach manuell erstellen.

Erstellen Sie eine neue Swift-Datei und das Popup-Fenster erscheint wie auf dem Bild oben, klicken Sie einfach auf "Überbrückungsheader erstellen".  

Dieser generierte Schnittstellen-Header sollte wie folgt benannt werden: "YourSDK-Swift.h". Dies ist wichtig, da wir ihn verwenden werden, um Swift-Code in Objective-C zu importieren.

Migrating_Objective_C_Framework_to_Swift_3.webp

Als Nächstes gehen Sie zu "Build Settings" Ihres Framework-Projekts und suchen Sie "Defines Module" und setzen Sie es auf "YES".

Nun, da wir alles eingerichtet haben, können wir unsere Swift-Datei wie folgt in Objective-C importieren:

#import <YourSDK/YourSDK-Swift.h>

und schon können Sie Swift verwenden, wenn Sie Glück haben.

Schritt 3 - Wie man Swift-Code in ObjC verwendet

Wir sind noch nicht fertig. Um Swift zu verwenden, müssen wir noch einige Anpassungen an unserem Code vornehmen. Die generierte Header-Datei ist Teil der öffentlichen Schnittstelle des Frameworks und nur Swift-Klassen, die als "Public" oder "Open" markiert sind, sind von Objective-C-Code aus zugänglich.

Außerdem müssen sie mit @objc vor dem Klassennamen gekennzeichnet sein und von NSObject erben. Zum Beispiel so:

@objc public class MyClass: NSObject { }

Das gilt auch für alles andere, Funktionen zum Beispiel müssen als "Public" gekennzeichnet sein und @objc vorangestellt haben, etwa so:

@objc public func doSomething().

Sie können auch @objcMembers anstelle von @objc vor dem Klassennamen hinzufügen, dann gilt es für alle Funktionen in Ihrer Klasse, so dass Sie es nicht separat hinzufügen müssen. Zum Beispiel:

@objcMembers public class MyClass: NSObject { } public func doSomething().

Schritt 4 - Privat machen

Jetzt können wir Swift innerhalb von Objective-C-Code verwenden, juhu ? Aber halt, wir haben jetzt ein großes Problem.

Indem wir public vor unsere Swift-Klassen und -Methoden setzen, machen wir sie, Sie ahnen es, öffentlich. Unser Framework braucht private Klassen, und so können wir nicht weitermachen.

Was sollen wir also tun? Nun, es gibt eine Möglichkeit:

  1. Nehmen wir unsere Testklasse, die wir mit einer Objective-C-Annotation versehen müssen:
@objc (MyClass) public class MyClass: NSObject { } @objc (doSomething) func doSomething().
  1. Dann erstellen wir eine Objective-C ".h" Datei, nennen wir sie "SwiftInterfaceFiles.h", in der wir die Schnittstelle unserer Swift Klasse und Methode erstellen:

"SwiftInterfaceFiles.h"

@interface MeineKlasse() - (void)doSomething; @end
  1. Der letzte Schritt ist der Import von "SwiftInterfaceFiles.h" in unsere Objective-C ".m" Datei.
#import "SwiftInterfaceFiles.h" MyClass *instanceOfMyClass = [MyClass new]; [instanceOfMyClass doSomething];

Schritt 5 - Funktioniert alles?

So weit, so gut. Wir können neuen Swift-Code erstellen, Objective-C-Wrapper erstellen, um öffentliche Probleme zu behandeln, und Swift verwenden. Allerdings gibt es einige Einschränkungen.

Hier sind einige Swift-Funktionen, die in Objective-C nicht verfügbar sind:

  • Wir können nur Swift-Enums vom Typ Int verwenden
  • Globale Variablen
  • Typ-Aliase
  • Strukturen
  • Unterklassenbildung von Swift
  • Funktionen der obersten Ebene

Wenn Sie auf ein Problem stoßen, bei dem eine Swift-Methode in Objective-C nicht sichtbar ist, obwohl Sie alles wie oben beschrieben gemacht haben, bedeutet dies wahrscheinlich, dass Sie versuchen, Swift-Funktionen zu verwenden, die in Objective-C nicht verfügbar sind. Eine Möglichkeit, damit umzugehen, besteht darin, eine Wrapper-Klasse zu erstellen, die diese nicht verfügbaren Funktionen verarbeiten kann und beim Dialog mit den Objective-C-Klassen aufgerufen wird.

Schritt 6 - Das Ende?

Wir haben uns damit beschäftigt, wie man Swift in Objective-C verwendet, für diesen Teil sind wir gut, das ist das Ende.

Aber was ist, wenn ich Objective-C in meinem Swift-Code verwenden möchte? Nun, das ist eine andere Geschichte.

Ihr Framework hat wahrscheinlich eine Header-Datei, in der Sie Dateien für die Verwendung in Projekten freigeben. Diese Dateien sind öffentlich und können in Swift verwendet werden. Das ist großartig! Das Problem entsteht, wenn wir privaten Objective-C-Code in Swift verwenden wollen. Wir können nicht auf ihn zugreifen. Wir können ihn nicht öffentlich machen, er sollte privat bleiben.

Leider hat Apple dafür keine Lösung, sie sagen, man solle ihn öffentlich machen, was nicht wirklich eine gute Praxis ist. Wir könnten modulemaps verwenden, aber das ist chaotisch und funktioniert manchmal nicht, und unsere privaten Dateien sind nicht wirklich privat, sie können immer noch von außen eingesehen werden.

Die einzige brauchbare Lösung, die ich gefunden habe, findet sich in diesem Artikel.

Das war's für den Moment, ich danke Ihnen für die Lektüre und hoffe, dass Apple eine bessere Lösung für die Verwendung von privaten Objective-C-Dateien in Swift finden wird. Bis wir uns wiedersehen.

Stefan Markovikj

Stefan Markovikj

Buchen Sie eine kostenlose Beratung

Wählen Sie Ihre Branche*

Bitte wählen Sie Ihre Branche*

Wählen Sie Ihren Servicetyp

Bitte wählen Sie Ihren Servicetyp

calendarWann passt es Ihnen am besten für ein kurzes Gespräch

Die mit * gekennzeichneten Felder sind Pflichtfelder

Alle Beiträge anzeigen