Unterklasse UIApplication mit Swift

91

In Ziel C war es einfach: Es war ausreichend, die Datei main.m zu aktualisieren und die Parameter UIApplicationMain () zu ändern

return UIApplicationMain(argc, argv, NSStringFromClass([CustomUIApplication class]), NSStringFromClass([AppDelegate class]));

Aber in Kürze gibt es keine main.m-Datei, da der Leitfaden sagt

"Code, der im globalen Bereich geschrieben wurde, wird als Einstiegspunkt für das Programm verwendet, sodass Sie keine Hauptfunktion benötigen."

Also, wie kann man UIApplication schnell unterordnen? Irgendein Vorschlag?

LombaX
quelle
1
Warum ist es vorzuziehen, UIApplicationMain()Parameter zu ändern und den Klassennamen NSPrincipalClassin der app-info.plist hinzuzufügen?
Andreas

Antworten:

172

HINWEIS Die Syntax ist für XCode 10.1 und Swift 5 Juni 2019 (Gutschriften aktualisiert matt Antwort hier && Tung Fam Antwort hier ), wenn Sie für die vorherigen Syntaxen suchen Blick auf die Edit - Sektion.

Ok, ich habe die Lösung gefunden

Zuerst habe ich festgestellt, dass sich oben in der Datei AppDelegate.swift diese Zeile befindet

@UIApplicationMain

Da diese Zeile außerhalb eines Bereichs liegt (auf Dateiebene), wird sie sofort ausgeführt, und ich gehe davon aus, dass der Compiler sie in eine Standardhauptfunktion übersetzt.

Also habe ich dies ausgehend von einer neuen Swift-Only-Anwendung getan:

  • auskommentiert @UIApplicationMain
  • hat eine main.swift-Datei wie diese hinzugefügt (FLApplication ist meine Unterklasse).
    WICHTIG, die Datei muss main.swift NAMED sein, da Anweisungen der obersten Ebene in anderen Dateien nicht unterstützt werden! Sie können den UIApplicationMain () -Aufruf in keiner anderen Datei hinzufügen, andernfalls wird folgende Fehlermeldung angezeigt:

Ausdrücke sind auf der obersten Ebene nicht zulässig

Dies ist die Datei main.swift

UIApplicationMain(
    CommandLine.argc, CommandLine.unsafeArgv, 
    NSStringFromClass(FLApplication.self), NSStringFromClass(AppDelegate.self)
)

Erstellen Sie dann eine schnelle Datei für die UIApplication-Unterklasse FLApplication.swift mit folgendem Code:

import UIKit
import Foundation

class FLApplication: UIApplication {
    override func sendEvent(_ event: UIEvent) {
        super.sendEvent(event)
        print("send event")
    }
}

Jetzt ist UIApplication korrekt in Unterklassen unterteilt und die Meldungen "Sendeereignis" werden im Protokoll angezeigt


ALTE BEARBEITUNGEN
Als Referenz, da sich dies von Version 1 zu Version 3 stark geändert hat, lasse ich hier alle vorherigen Änderungen


EDIT - MÄRZ 2015

Wie von Hu Junfeng kommentiert, sind jetzt die Erklärungen zu UIApplicationMainund die Datei main.swift im Abschnitt Attribute von The Swift Language Reference: Link dokumentiert

Wie von Thomas Verbeek kommentiert In der XCode 6.3 Beta stellen Sie möglicherweise fest, dass C_ARGC und C_ARGV in Process.argc bzw. Process.unsafeArgv umbenannt wurden. Ihr UIApplicationMain-Aufruf in der Datei main.swift muss aktualisiert werden auf:

UIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(FLApplication), NSStringFromClass(AppDelegate))

Die Pre-XCode 8-Syntax war

import Foundation
import UIKit

UIApplicationMain(C_ARGC, C_ARGV, NSStringFromClass(FLApplication), NSStringFromClass(AppDelegate))

EDIT - DEZ 2016

Lösung für Xcode 8 vor Beta 6

import Foundation
import UIKit

UIApplicationMain(
    CommandLine.argc,
    UnsafeMutableRawPointer(CommandLine.unsafeArgv)
        .bindMemory( 
            to: UnsafeMutablePointer<Int8>.self, 
            capacity: Int(CommandLine.argc)),
    NSStringFromClass(FLApplication.self),
    NSStringFromClass(AppDelegate.self)
)
LombaX
quelle
Ich versuche zu verstehen, ob es möglich ist, UIApplicationMain () direkt in der Datei AppDelegate.swift aufzurufen, da es anscheinend eine "schnelle Version" dieser Methode gibt, aber ich habe einen Compilerfehler. Ich werde einige Tests durchführen Suche nach einer "nur schnell" Lösung
LombaX
Unglaublich cool. Ich bin gespannt, was der Anwendungsfall für das Überschreiben sendEvent:heutzutage ist (ich erinnere mich, dass ich es in iOS 3 tun musste ...)
matt
2
Falls jemand es wissen möchte UIApplicationMainund main.swiftim Abschnitt Attribute der Swift Language Reference dokumentiert ist. developer.apple.com/library/ios/documentation/Swift/Conceptual/…
hujunfeng
Vielen Dank für den Hinweis, ich bin zu 99% sicher, dass es in der ersten Version des Swift-Handbuchs nicht dokumentiert war :-) Ich werde jedoch die Antwort aktualisieren und Ihre Informationen hinzufügen.
LombaX
5
Gute Antwort. In der XCode 6.3 Beta finden Sie dies möglicherweise C_ARGCund C_ARGVwurden in Process.argcbzw. Process.unsafeArgvumbenannt. Ihr UIApplicationMain-Aufruf in der Datei main.swift muss aktualisiert werden aufUIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(KBApplication), NSStringFromClass(AppDelegate))
Thomas Verbeek
4

Eine Alternative besteht darin, es zu erweitern, UIApplicationanstatt es zu unterklassifizieren. Laut dem von Apple veröffentlichten iBook können Erweiterungen in Swift:

Hinzufügen von berechneten Eigenschaften und berechneten statischen Eigenschaften Definieren von Instanzmethoden und Typmethoden Bereitstellen neuer Initialisierer Definieren von Indizes Definieren und Verwenden neuer verschachtelter Typen Stellen Sie sicher, dass ein vorhandener Typ einem Protokoll entspricht

Auszug aus: Apple Inc. „Die schnelle Programmiersprache.

Wenn Ihre Anforderungen in der Unterklasse UIApplicationdurch diese Funktionen erfüllt werden, ist möglicherweise eine Erweiterung der richtige Weg.

Cezar
quelle
5
netter Rat - nicht imho antworten :)
Daij-Djan
1
  1. Erstellen Sie eine Unterklasse von UIApplicationund fügen Sie Ihre Logik hinzu

    import UIKit
    
    class CustomUIApplication: UIApplication {
        override func sendEvent(_ event: UIEvent) {
            super.sendEvent(event)
        }
    }
  2. Erstellen Sie eine main.swiftDatei, die die UIApplicationMain()globale Funktion [Info] aufruft. Dies ist der neue Einstiegspunkt Ihrer Anwendung, der vom Betriebssystem aufgerufen wird. Diese Funktion empfängt Argumente von aufgerufenen Funktionen, UIApplicationKlassennamen und UIApplicationDelegateKlassennamen und startet die Hauptlaufschleife.

    import UIKit
    
    UIApplicationMain(
        CommandLine.argc,
        CommandLine.unsafeArgv,
    
        NSStringFromClass(CustomUIApplication.self), //was created at step 1
        NSStringFromClass(AppDelegate.self)
    )
  3. Entfernen / kommentieren Sie die @UIApplicationMainAnmerkung zum Standard AppDelegate.

    @UIApplicationMainerzeugt main.swift.

    Wenn Sie dies nicht tun, wird ein Kompilierungsfehler angezeigt:

    UIApplicationMain Das Attribut kann nicht in einem Modul verwendet werden, das Code der obersten Ebene enthält

    //@UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
        //...
    }
yoAlex5
quelle