Come posso ottenere un riferimento al delegato dell'app in Swift?


409

Come posso ottenere un riferimento al delegato dell'app in Swift?

In definitiva, voglio usare il riferimento per accedere al contesto dell'oggetto gestito.


8
Si noti che alcuni considererebbero l'uso del delegato dell'app come contenitore per il contesto dell'oggetto gestito o altri oggetti "globali" come anti-pattern. Prendi in considerazione la possibilità che il delegato dell'app passi il MOC al controller, piuttosto che farlo trovare al controller.
Kristopher Johnson,

1
@KristopherJohnson Ehi Kris, come posso facilitare l'AppDelegate iniettando dipendenze nei controller di visualizzazione? Crea un'istanza del controller di visualizzazione in modo programmatico e usa la riflessione per decidere cosa istanziare / iniettare, ricorsivamente? Ci sono dei framework che possono aiutare in questo? Se devo farlo manualmente per ogni controller di visualizzazione, il mio AppDelegate sarà enorme! Oh, preferibilmente senza creare una fabbrica per tutto :)
Jimbo

1
Una rapida ricerca ha trovato Swinject che ha anche il cablaggio automatico :)
Jimbo

6
Per i programmatori che sconsigliano di inserire qualcosa di "estraneo" nel delegato dell'app, è un po 'assurdo perché la documentazione di Apple afferma esplicitamente che uno "crucial role"dei UIApplicationDelegatesingleton è "...to store your app’s central data objects or any content that does not have an owning view controller." developer.apple.com/documentation/uikit/uiapplicationdelegate
bsod

Risposte:


757

L'altra soluzione è corretta in quanto ti fornirà un riferimento al delegato dell'applicazione, ma ciò non ti consentirà di accedere a metodi o variabili aggiunti dalla sottoclasse di UIApplication, come il contesto dell'oggetto gestito. Per risolvere questo problema, basta eseguire il downcast su "AppDelegate" o come mai viene chiamata la sottoclasse di UIApplication. In Swift 3, 4 e 5 , questo viene fatto come segue:

let appDelegate = UIApplication.shared.delegate as! AppDelegate
let aVariable = appDelegate.someVariable

10
Nel caso in cui qualcuno abbia ancora problemi, il targeting per OS X richiede l'importazione di Cocoa perché funzioni per NSApplication.sharedApplication (). Immagino che iOS avrebbe bisogno dell'equivalente.
smaurice,

2
Questa è la più utile delle due risposte.
Joe,

3
@zacjordaan Usando questo metodo, otterrai il completamento automatico per la proprietà, ma in realtà non funzionerà. In questo modo creerà una nuova istanza della classe AppDelegate ogni volta che la usi. Stai meglio usando il delegato accessibile tramite il singleton sharedApplication. E per quanto riguarda la seconda domanda, sì, probabilmente vuoi usare una costante. Anche se, potresti modificare le proprietà di AppDelegate, probabilmente non dovrai riassegnare il puntatore a nient'altro, nel qual caso non è necessaria una variabile. Questo dipende completamente da te. Fai quello che soddisfa le tue esigenze.
Mick MacCallum,

2
Ottimo consiglio! Avevo erroneamente pensato che AppDelegate () fosse singleton, ma dopo aver pensato a quello che hai detto mi sono reso conto che se fosse così non ci sarebbe un modello di applicazione condiviso da usare in questo modo. Ovviamente non voglio generare casi non necessari se non devo, quindi la tua costante dichiarazione si adatterà perfettamente; Grazie.
Zacjordaan,

4
Non voglio aggiungere questo come risposta separata, ma per ottenere AppDelegate con i tuoi metodi, proprietà nel progetto in cui vengono utilizzati sia Swift che Obj-c Dovresti aggiungere #import "AppDelegate.h" a "ProjectName-BridgingHeader .h "
Marcin Mierzejewski,

44

Rapido 4.2

In Swift, è facile accedere ai tuoi VC

extension UIViewController {
    var appDelegate: AppDelegate {
    return UIApplication.shared.delegate as! AppDelegate
   }
}

26

Costruttori di convenienza

Aggiungi in AppDelegate Class alla fine del codice

Swift 5

func appDelegate() -> AppDelegate {
    return UIApplication.shared.delegate as! AppDelegate
}

Per utilizzare il riferimento AppDelegate nella tua classe?


Chiama il metodo AppDelegate

AppDelegate (). setRoot ()


Sarebbe bello spiegare cosa fa setRoot () e quando chiamarlo. es. va bene chiamarlo da un ViewController? Da un test unitario in cui la finestra non è ancora impostata? Più contesto sarebbe fantastico.
Houman,

@Houman setRoot è il metodo di AppDelegate che può essere utilizzato per passare da più root a ParentViewController e può essere qualsiasi metodo. La discussione riguarda come ottenere il riferimento di AppDelegate per un ulteriore accesso, ma spero che anche setRoot debba essere chiaro.
AiOsN il

19

È praticamente lo stesso di Objective-C

let del = UIApplication.sharedApplication().delegate

19

Questo potrebbe essere usato per OS X

let appDelegate = NSApplication.sharedApplication().delegate as AppDelegate
var managedObjectContext = appDelegate.managedObjectContext?

3
O semplicementelet appDelegate = NSApp.delegate as AppDelegate
Vladimir Prudnikov il

1
In Swift 3 usalet appDelegate = NSApplication.shared().delegate as AppDelegate
Dirk

4
In Swift 4 :NSApp.delegate as? AppDelegate
Nick,

12

Ecco la versione Swift 2.0:

let delegate = UIApplication.sharedApplication().delegate as? AppDelegate

E per accedere al contesto dell'oggetto gestito:

    if let delegate = UIApplication.sharedApplication().delegate as? AppDelegate {

        let moc = delegate.managedObjectContext

        // your code here

    }

oppure, usando guard:

    guard let delegate = UIApplication.sharedApplication().delegate as? AppDelegate  else {
        return
    }

    let moc = delegate.managedObjectContext

    // your code here

10

SWIFT <3

Creare un metodo nella classe AppDelegate per es

func sharedInstance() -> AppDelegate{
        return UIApplication.sharedApplication().delegate as! AppDelegate
    }

e chiamalo un po 'altrove per es

let appDelegate : AppDelegate = AppDelegate().sharedInstance()

SWIFT> = 3.0

func sharedInstance() -> AppDelegate{
    return UIApplication.shared.delegate as! AppDelegate
}

2
anche questo funziona e mi piace l'idea della denominazione sharedInstance. Grazie!
John Griffiths,

2
Il tuo esempio creerebbe comunque un'istanza di un nuovo AppDelegateoggetto ogni volta che hai chiamatoAppDelegate().sharedInstance()
pxpgraphics,

1
Mi piace questa soluzione meglio di quella accettata (che è "senza fronzoli" dettagliata se devi usarla dappertutto). Stavo pensando di sperimentare con un extensionfor NSApplicationprima di trovare questa risposta, ma è molto meglio. Al giorno d'oggi probabilmente vorresti usare una proprietà di sola lettura calcolata per classe shared, forse vorresti pubblicare un aggiornamento per Swift 3?
Patru,

1
Sono attualmente in fase di refactoring del mio codice da utilizzare, static var shared : TournamentDelegate? { get { return NSApplication.shared().delegate as? TournamentDelegate } }che è più in linea con lo stile Swift 3 in via di sviluppo dell'utilizzo delle proprietà di sola lettura calcolate per questo tipo di cose. Probabilmente sarò in grado di abbandonare ?una volta terminato il refactoring, non credi? (Mi dispiace, la formattazione del codice nei commenti è sempre un casino.)
Patru,

@ pxpgraphics UIApplication è una classe singleton, quindi non devi preoccuparti di un'istanza multipla.
Abhijith il


6

Prova semplicemente questo:

Swift 4

// Call the method
(UIApplication.shared.delegate as? AppDelegate)?.whateverWillOccur()

dove nel tuo AppDelegate:

// MARK: - Whatever
func whateverWillOccur() {

    // Your code here.

}

5

Ecco un'estensione per UIApplicationDelegateevitare di codificare il AppDelegatenome della classe:

extension UIApplicationDelegate {

    static var shared: Self {    
        return UIApplication.shared.delegate! as! Self
    }
}

// use like this:
let appDelegate = MyAppDelegate.shared // will be of type MyAppDelegate

su Mac per NSApplicationDelegatequesto mi dà: 'Self' is only available in a protocol or as the result of a method in a class; did you mean 'AppDelegate'?. È obsoleto?
pkamb,

@pkamb L'ho appena provato in un nuovo progetto e non ho questo errore. Ho sostituito UIApplicationDelegateda NSApplicationDelegatee UIApplicationda NSApplication.
nyg

5
  1. Accertati di import UIKit

  2. let appDelegate = UIApplication.sharedApplication().delegate! as! AppDelegate


4

è molto semplice

Istanza delegata dell'app

let app = UIApplication.shared.delegate as! AppDelegate

puoi chiamare un metodo con una sintassi di una riga

app.callingMethod()

puoi accedere a una variabile con questo codice

app.yourVariable = "Assigning a value"

2

Nel mio caso, mi mancava import UIKitin cima alla mia NSManagedObjectsottoclasse. Dopo averlo importato, ho potuto rimuovere quell'errore come UIApplicationè la parte diUIKit

Spero che aiuti gli altri !!!


2

Lo uso in Swift 2.3.

1. in classe AppDelegate

static let sharedInstance: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

2.Call AppDelegate with

let appDelegate = AppDelegate.sharedInstance

2
extension AppDelegate {

    // MARK: - App Delegate Ref
    class func delegate() -> AppDelegate {
        return UIApplication.shared.delegate as! AppDelegate
    }
}

2

A partire da iOS 12.2 e Swift 5.0, AppDelegatenon è un simbolo riconosciuto. UIApplicationDelegateè. AppDelegatePertanto, le risposte a cui si fa riferimento non sono più corrette. La seguente risposta è corretta ed evita il riavvolgimento forzato, che alcuni sviluppatori considerano un odore di codice:

import UIKit

extension UIViewController {
  var appDelegate: UIApplicationDelegate {
    guard let appDelegate = UIApplication.shared.delegate else {
      fatalError("Could not determine appDelegate.")
    }
    return appDelegate
  }
}

1
In swift5 il tuo codice darà l'avvertimento "UIApplication.delegate deve essere usato solo dal thread principale". Puoi aggiornare la risposta.
Mahesh Narla,

che fatalErrorè funzionalmente equivalente a una forza da scartare!
pkamb,

1

In Swift 3.0 puoi ottenere il appdelegateriferimento di

let appDelegate = UIApplication.shared.delegate as! AppDelegate

0

In Xcode 6.2, anche questo funziona

let appDelegate = UIApplication.sharedApplication().delegate! as AppDelegate

let aVariable = appDelegate.someVariable

2
v01d, da dove l'hai preso?
NSPratik,
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.