Gibt es eine Alternative zu initialize () in macOS jetzt, wo Swift es veraltet hat?

18

Objective-C deklariert eine Klassenfunktion, initialize (), die einmal für jede Klasse ausgeführt wird, bevor sie verwendet wird. Es wird oft als Einstiegspunkt für den Austausch von Methodenimplementierungen (swizzling) verwendet. Seine Verwendung war in Swift 3.1 veraltet.

Das habe ich früher gemacht:

%Vor%

Wie kann ich dasselbe ohne initialize erreichen?

Ich brauche es für ein Framework, so dass das Anrufen von etwas im AppDelegate ein No-Go ist. Ich brauche es vor applicationDidFinishLaunching aufgerufen.

Ich mag diese Lösung. Es ist genau das, wonach ich suche, aber es ist für iOS. Ich brauche es für MacOS. Könnte jemand eine MacOS-Version vorschlagen?

Um genau zu sein, brauche ich das Äquivalent davon, aber für Mac OS:

%Vor%

Ich habe versucht, verschiedene Eigenschaften in NSApplication ohne Erfolg zu überschreiben.

Die Lösung muss in reinem Swift sein. Kein Ziel-C.

    
Sindre Sorhus 28.02.2018, 12:23
quelle

3 Antworten

6

Nein, eine schnelle Alternative zu initialize() existiert nicht, hauptsächlich weil Swift statisch versendet wird, sodass Methodenaufrufe nicht abgefangen werden können. Und es wird wirklich nicht mehr benötigt, da die Methode üblicherweise verwendet wurde, um statische Variablen aus Objective-C-Dateien zu initialisieren, und in Swift sind statische / globale Variablen immer faul und können mit dem Ergebnis eines Ausdrucks initialisiert werden (was in Objective- C).

Selbst wenn es möglich wäre, etwas Ähnliches zu erreichen, würde ich Sie davon abraten, Dinge ohne das Wissen der Framework-Benutzer implizit auszuführen. Ich würde empfehlen, irgendwo in der Bibliothek eine configure -Methode hinzuzufügen und die Benutzer Ihrer Bibliothek aufzufordern, sie aufzurufen. Auf diese Weise haben sie die Kontrolle über den Initialisierungspunkt. Es gibt nur wenige Dinge, die schlimmer sind als ein Framework, mit dem ich verlinkt habe, aber nicht mehr (oder noch nicht), um Code ohne meine Zustimmung auszuführen.

Es ist nur vernünftiger, Framework-Benutzern die Kontrolle darüber zu geben, wann sie den Framework-Code starten wollen. Wenn Ihr Code tatsächlich am Anfang des Anwendungslebenszyklus ausgeführt werden muss, bitten Sie die Framework-Benutzer, den Aufruf an den Framework-Einstiegspunkt vor allen anderen Aufrufen durchzuführen. Es ist auch in ihrem Interesse, dass Ihr Framework richtig konfiguriert ist.

ZB:

%Vor%     
Cristik 04.03.2018 19:21
quelle
3

Wie bereits von anderen erwähnt, ist es in einem Framework in Swift nicht möglich, das zu tun, wonach Sie fragen. Das Erreichen der Funktionalität aus der Anwendung selbst (wo diese Art von Verhalten gehört) ist jedoch ziemlich einfach - es gibt keine Notwendigkeit, sich mit Benachrichtigungen oder Selektoren herumzuärgern. Sie überschreiben einfach das init Ihres NSApplicationDelegate (oder UIApplicationDelegate ) und richten dort Ihren Klasseninitialisierer ein:

%Vor%

Und die entsprechende statische Funktion:

%Vor%

Dies wird die gleiche Funktionalität wie initialize() erreichen.

    
Oskar 08.03.2018 15:54
quelle
2

BEARBEITEN: Seit ich diese Antwort geschrieben habe, hat das OP der Frage in einer Bearbeitung "pure Swift" hinzugefügt. Ich lasse diese Antwort jedoch hier, weil dies der einzig richtige Weg ist, dies zum Zeitpunkt des Schreibens zu tun. Hoffentlich werden die Modul-Initialisierungs-Hooks in Swift 6 oder 7 oder 8 hinzugefügt, aber ab März 2018 ist pure Swift das falsche Werkzeug für diesen Anwendungsfall.

Ursprüngliche Antwort folgt:

Leider hat Swift kein direktes Äquivalent zu den alten Methoden initialize() und load() , so dass dies nicht in reinem Swift AFAIK gemacht werden kann. Wenn Sie jedoch nicht abgeneigt sind, eine kleine Menge von Objective-C in Ihr Projekt zu mischen, ist dies nicht schwer. Erstellen Sie einfach eine Swift-Klasse, die vollständig Objective-C ausgesetzt ist:

%Vor%

Fügen Sie dann diese kurze Objective-C-Datei zum Projekt hinzu:

%Vor%

Wenn diese zwei Codeelemente vorhanden sind, sollte eine App, die mit Ihrem Framework verknüpft wird, "App wird gestartet" auf der Konsole geloggt werden, bevor applicationDidFinishLaunching aufgerufen wird.

Alternativ können Sie, wenn Sie bereits eine öffentliche ObjC-visible-Klasse in Ihrem Modul haben, dies tun, ohne die Laufzeitfunktionen über eine Kategorie zu verwenden:

%Vor%

und:

%Vor%     
Charles Srstka 02.03.2018 23:22
quelle

Tags und Links