¿Cómo obtengo una referencia al delegado de la aplicación en Swift?


409

¿Cómo obtengo una referencia al delegado de la aplicación en Swift?

Finalmente, quiero usar la referencia para acceder al contexto del objeto administrado.


8
Tenga en cuenta que algunos considerarían el uso del delegado de la aplicación como un contenedor para el contexto del objeto administrado u otros objetos "globales" como un antipatrón. Considere que el delegado de la aplicación pase el MOC al controlador, en lugar de hacer que el controlador lo encuentre.
Kristopher Johnson

1
@KristopherJohnson Hola Kris, ¿cómo puedo facilitar que AppDelegate inyecte dependencias en los controladores de vista? ¿Instanciar el controlador de vista mediante programación y usar la reflexión para decidir qué instanciar / inyectar, recursivamente? ¿Hay algún marco que pueda ayudar con esto? Si tengo que hacer esto para cada controlador de vista de forma manual, ¡mi AppDelegate será enorme! Oh, preferiblemente sin crear una fábrica para todo :)
Jimbo

1
Una búsqueda rápida encontró Swinject que también tiene cableado automático :)
Jimbo

66
Para los programadores que aconsejan no poner nada "extraño" en el delegado de la aplicación, es un poco absurdo porque la documentación de Apple establece explícitamente que uno "crucial role"de los UIApplicationDelegatesingleton es "...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

Respuestas:


757

La otra solución es correcta, ya que le dará una referencia al delegado de la aplicación, pero esto no le permitirá acceder a ningún método o variable agregado por su subclase de UIApplication, como el contexto de su objeto administrado. Para resolver esto, simplemente baja a "AppDelegate" o como se llame a tu subclase UIApplication. En Swift 3, 4 y 5 , esto se hace de la siguiente manera:

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

10
En caso de que alguien siga teniendo problemas, apuntar a OS X requiere que importe Cocoa para que esto funcione para NSApplication.sharedApplication (). Supongo que iOS necesitaría el equivalente.
smaurice

2
Esta es la más útil de las dos respuestas.
Joe

3
@zacjordaan Usando ese método, obtendrá autocompletado para la propiedad, pero en realidad no funcionará. De esa manera creará una nueva instancia de la clase AppDelegate cada vez que la use. Es mejor usar el delegado accesible a través del singleton sharedApplication. Y en lo que respecta a su segunda pregunta, sí, probablemente quiera usar una constante. Aunque es posible que esté cambiando las propiedades del AppDelegate, probablemente no reasigne el puntero a ninguna otra cosa, en cuyo caso, no hay necesidad de una variable. Sin embargo, esto depende completamente de usted. Haz lo que se adapte a tus necesidades.
Mick MacCallum

2
Excelente consejo! Había pensado erróneamente que AppDelegate () era singleton, pero después de pensar en lo que dijiste, me di cuenta de que si fuera así, no habría un patrón de Aplicación compartida para que lo usemos de esta manera. Por supuesto, no quiero generar instancias innecesarias si no es necesario, por lo que su declaración constante se adaptará perfectamente; Gracias.
zacjordaan

44
No quiero agregar esto como respuesta por separado, pero para obtener AppDelegate con sus propios métodos, propiedades en el proyecto donde se usan Swift y Obj-c. Debe agregar #import "AppDelegate.h" a "ProjectName-BridgingHeader .h "
Marcin Mierzejewski

44

Swift 4.2

En Swift, fácil acceso en sus VC

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

26

Constructores de conveniencia

Agregue la clase AppDelegate al final del código

Swift 5

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

¿Para usar la referencia de AppDelegate en tu clase?


Llame al método AppDelegate

appDelegate (). setRoot ()


Sería genial explicar qué hace setRoot () y cuándo llamarlo. por ejemplo, ¿está bien llamarlo desde un ViewController? ¿De una prueba de unidad donde la ventana aún no está configurada? Más contexto sería genial.
Houman

@Houman setRoot es un método de AppDelegate que podría usarse para cambiar entre múltiples Raíces o ParentViewController y podría ser cualquier método. La discusión trata sobre cómo obtener la referencia de AppDelegate para un mayor acceso, pero espero que setRoot también sea claro.
AiOsN

19

Es casi lo mismo que en Objective-C

let del = UIApplication.sharedApplication().delegate

19

Esto podría usarse para OS X

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

3
O simplementelet appDelegate = NSApp.delegate as AppDelegate
Vladimir Prudnikov

1
En Swift 3 usolet appDelegate = NSApplication.shared().delegate as AppDelegate
Dirk

44
En Swift 4 :NSApp.delegate as? AppDelegate
Nick

12

Aquí está la versión 2.0 de Swift:

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

Y para acceder al contexto del objeto gestionado:

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

        let moc = delegate.managedObjectContext

        // your code here

    }

o, usando guardia:

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

    let moc = delegate.managedObjectContext

    // your code here

10

SWIFT <3

Crear un método en AppDelegate Class para ex

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

y llamarlo en otro lugar para ex

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

SWIFT> = 3.0

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

2
esto también funciona, y me gusta la idea del nombre de SharedInstance. ¡Gracias!
John Griffiths

2
Su ejemplo aún creará una instancia de un nuevo AppDelegateobjeto cada vez que llameAppDelegate().sharedInstance()
pxpgraphics

1
Me gusta esta solución mejor que la aceptada (que es "poco inteligente" detallada si tiene que usarla por completo). Estaba pensando en experimentar con una extensionpara NSApplicationantes de encontrar esta respuesta, pero esto es mucho mejor. Hoy en día, es probable que desee utilizar una propiedad de solo lectura calculada por clase shared, ¿tal vez le gustaría publicar una actualización para Swift 3?
Patru

1
En realidad, estoy en el proceso de refactorizar mi código para usarlo, lo static var shared : TournamentDelegate? { get { return NSApplication.shared().delegate as? TournamentDelegate } }que está más en línea con el estilo Swift 3 en desarrollo de usar propiedades de solo lectura computadas para este tipo de cosas. Probablemente podré dejarlo ?una vez que se complete la refactorización, ¿no crees? (Lo sentimos, el formato de código en los comentarios siempre es un desastre.)
Patru

@ pxpgraphics UIApplication es una clase singleton, por lo que no debe preocuparse por la creación de instancias múltiples.
Abhijith


6

Prueba simplemente esto:

Swift 4

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

donde en tu AppDelegate:

// MARK: - Whatever
func whateverWillOccur() {

    // Your code here.

}

5

Aquí hay una extensión UIApplicationDelegateque evita codificar el AppDelegatenombre de la clase:

extension UIApplicationDelegate {

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

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

en el Mac para NSApplicationDelegateesto me da: 'Self' is only available in a protocol or as the result of a method in a class; did you mean 'AppDelegate'?. ¿Está desactualizado?
pkamb

@pkamb Lo acabo de probar en un nuevo proyecto y no tengo este error. He sustituido UIApplicationDelegatepor NSApplicationDelegatey UIApplicationpor NSApplication.
nyg

5
  1. Asegúrese import UIKit

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


4

Es muy simple

Instancia delegada de la aplicación

let app = UIApplication.shared.delegate as! AppDelegate

puedes llamar a un método con sintaxis de una línea

app.callingMethod()

puedes acceder a una variable con este código

app.yourVariable = "Assigning a value"

2

En mi caso, faltaba import UIKiten la parte superior de mi NSManagedObjectsubclase. Después de importarlo, podría eliminar ese error como UIApplicationes parte deUIKit

Espero que ayude a los demás!


2

Lo uso en Swift 2.3.

1.en la clase AppDelegate

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

2. Llame a la aplicación Delegar con

let appDelegate = AppDelegate.sharedInstance

2
extension AppDelegate {

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

2

A partir de iOS 12.2 y Swift 5.0, AppDelegateno es un símbolo reconocido. UIApplicationDelegatees. Por lo tanto, las respuestas a las que AppDelegatese hace referencia ya no son correctas. La siguiente respuesta es correcta y evita el desenvolvimiento forzado, que algunos desarrolladores consideran un olor a código:

import UIKit

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

1
En swift5, su código mostrará la advertencia "UIApplication.delegate debe usarse solo desde el hilo principal". ¿Puedes actualizar la respuesta?
Mahesh Narla

eso fatalErrores funcionalmente equivalente a una fuerza de desenvolver!
pkamb

1

En Swift 3.0 puede obtener la appdelegatereferencia por

let appDelegate = UIApplication.shared.delegate as! AppDelegate

0

En el Xcode 6.2, esto también funciona

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

let aVariable = appDelegate.someVariable

2
v01d, ¿de dónde has sacado eso?
NSPratik
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.