Applicazione della sottoclasse UIA con Swift


92

In Objective C era semplice: bastava aggiornare il file main.m e cambiare i parametri UIApplicationMain ()

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

Ma in swift non esiste un file main.m, poiché dice la guida

"Il codice scritto in ambito globale viene utilizzato come punto di ingresso per il programma, quindi non è necessaria una funzione principale."

Quindi, come sottoclassare UIApplication in swift ?? Qualche suggerimento?


1
Perché sarebbe preferibile modificare i UIApplicationMain()parametri piuttosto che aggiungere il nome della classe NSPrincipalClassin app-info.plist?
Andreas

Risposte:


173

NOTA la sintassi è stato aggiornato per XCode 10.1 e Swift 5 a giugno 2019 (crediti a risposta di Matt qui && risposta di Tung Fam qui ), se siete alla ricerca per le sintassi precedenti cerca nella sezione di modifica.

Ok, ho trovato la soluzione

Per prima cosa, ho notato che, all'inizio del file AppDelegate.swift, c'è questa riga

@UIApplicationMain

Poiché questa riga è al di fuori di qualsiasi ambito (è a livello di file), viene eseguita immediatamente e presumo che il compilatore la traduca in una funzione principale standard.

Quindi l'ho fatto, partendo da una nuova applicazione Swift-Only:

  • commentata @UIApplicationMain
  • aggiunto un file main.swift come questo (FLApplication è la mia sottoclasse).
    IMPORTANTE il file DEVE ESSERE NOMINATO main.swift, poiché le istruzioni di primo livello non sono supportate su altri file! Non puoi aggiungere la chiamata UIApplicationMain () all'interno di qualsiasi altro file, altrimenti riceverai questo errore:

Le espressioni non sono consentite al livello superiore

Questo è il file main.swift

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

Quindi, crea un file swift per la sottoclasse UIApplication, FLApplication.swift, con questo codice:

import UIKit
import Foundation

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

ora, UIApplication è correttamente sottoclasse e vedrai i messaggi di "invio evento" nel log


VECCHIE MODIFICHE
Per riferimento, poiché questo è cambiato molto dalla versione 1 alla versione 3, lascio qui tutte le modifiche precedenti


EDIT - MARZO 2015

Come commentato da Hu Junfeng, ora le spiegazioni UIApplicationMaine il file main.swift sono documentati nella sezione Attributes di The Swift Language Reference: Link

Come commentato da Thomas Verbeek In XCode 6.3 Beta, potresti scoprire che C_ARGC e C_ARGV sono stati rinominati rispettivamente Process.argc e Process.unsafeArgv. La tua chiamata UIApplicationMain nel file main.swift dovrà essere aggiornata a:

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

La sintassi precedente a XCode 8 era

import Foundation
import UIKit

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

EDIT - DIC 2016

Soluzione per Xcode 8, prima della 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)
)

Sto cercando di capire se è possibile chiamare UIApplicationMain () direttamente nel file AppDelegate.swift, dato che sembra che ci sia una "versione rapida" di questo metodo, ma ho un errore del compilatore, farò alcuni test alla ricerca di una soluzione "rapida"
LombaX

Incredibilmente cool. Sono curioso di sapere quale sia il caso d'uso per l'override al sendEvent:giorno d'oggi (ricordo di doverlo fare in iOS 3 ...)
matt

2
Nel caso qualcuno volesse sapere, UIApplicationMaine main.swiftsono documentati nella sezione Attributi di The Swift Language Reference. developer.apple.com/library/ios/documentation/Swift/Conceptual/…
hujunfeng

Grazie per il suggerimento, sono sicuro al 99% che nella prima versione del manuale Swift non fosse documentato :-) comunque aggiornerò la risposta aggiungendo le tue informazioni.
LombaX

5
Bella risposta. In XCode 6.3 Beta, potresti scoprire che C_ARGCe C_ARGVsono stati rinominati rispettivamente in Process.argce Process.unsafeArgv. La chiamata UIApplicationMain nel file main.swift dovrà essere aggiornata aUIApplicationMain(Process.argc, Process.unsafeArgv, NSStringFromClass(KBApplication), NSStringFromClass(AppDelegate))
Thomas Verbeek

4

Un'alternativa è estenderlo UIApplicationinvece di sottoclassarlo. Secondo l' iBook rilasciato da Apple, le estensioni in Swift possono:

Aggiungere proprietà calcolate e proprietà statiche calcolate Definire metodi di istanza e metodi di tipo Fornire nuovi inizializzatori Definire pedici Definire e utilizzare nuovi tipi annidati Rendere un tipo esistente conforme a un protocollo

Estratto da: Apple Inc. “The Swift Programming Language.

Se le tue esigenze nella sottoclasse UIApplicationsono soddisfatte da queste capacità, un'estensione potrebbe essere la strada da percorrere.


5
bel consiglio - non rispondere imho :)
Daij-Djan

1
  1. Crea una sottoclasse di UIApplicatione aggiungi la tua logica

    import UIKit
    
    class CustomUIApplication: UIApplication {
        override func sendEvent(_ event: UIEvent) {
            super.sendEvent(event)
        }
    }
  2. Creare un main.swiftfile che richiami la UIApplicationMain()funzione globale [Informazioni su] , che è il nuovo punto di ingresso dell'applicazione che viene chiamato dal sistema operativo. Questa funzione riceve l'argomento dalla funzione chiamata, il UIApplicationnome della UIApplicationDelegateclasse , il nome della classe e avvia il ciclo di esecuzione principale.

    import UIKit
    
    UIApplicationMain(
        CommandLine.argc,
        CommandLine.unsafeArgv,
    
        NSStringFromClass(CustomUIApplication.self), //was created at step 1
        NSStringFromClass(AppDelegate.self)
    )
  3. Rimuovi / commenta l' @UIApplicationMainannotazione sul valore predefinito AppDelegate.

    @UIApplicationMaingenera main.swift.

    Se non lo fai, otterrai un errore di compilazione:

    UIApplicationMain l'attributo non può essere utilizzato in un modulo che contiene codice di primo livello

    //@UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
        //...
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.