Como obtenho uma referência ao delegado do aplicativo no Swift?

409

Como obtenho uma referência ao delegado do aplicativo no Swift?

Por fim, quero usar a referência para acessar o contexto do objeto gerenciado.

AperioOculus
fonte
8
Observe que alguns considerariam o uso do delegado do aplicativo como um contêiner para o contexto de objeto gerenciado ou outros objetos "globais" como um antipadrão. Considere pedir ao delegado do aplicativo que passe o MOC para o controlador, em vez de fazer com que o controlador o encontre.
precisa
1
@KristopherJohnson Hey Kris, como posso facilitar o AppDelegate que injeta dependências nos controladores de exibição? Instancie o controlador de exibição programaticamente e use a reflexão para decidir o que instanciar / injetar, recursivamente? Existem estruturas que podem ajudar com isso? Se eu tiver que fazer isso manualmente para cada controlador de exibição, meu AppDelegate será enorme! Oh, de preferência sem a criação de uma fábrica para tudo :)
Jimbo
1
Uma busca rápida encontrada Swinject que também tem auto-fiação :)
Jimbo
6
Para os programadores que desaconselham colocar nada "estranho" na delegado do aplicativo, que é um pouco absurdo, porque a documentação da Apple afirma explicitamente que a "crucial role"do 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

Respostas:

757

A outra solução está correta, pois fornecerá uma referência ao delegado do aplicativo, mas isso não permitirá que você acesse quaisquer métodos ou variáveis ​​adicionados pela sua subclasse de UIApplication, como o contexto do objeto gerenciado. Para resolver isso, basta fazer o downcast para "AppDelegate" ou como sua subclasse UIApplication é chamada. Nos Swift 3, 4 e 5 , isso é feito da seguinte maneira:

let appDelegate = UIApplication.shared.delegate as! AppDelegate
let aVariable = appDelegate.someVariable
Mick MacCallum
fonte
10
Caso alguém ainda esteja tendo problemas, o direcionamento para o OS X exige que você importe o Cocoa para que isso funcione no NSApplication.sharedApplication (). Eu acho que o iOS precisaria do equivalente.
precisa saber é
2
Essa é a mais útil das duas respostas.
Joe
3
@zacjordaan Usando esse método, você obterá o preenchimento automático da propriedade, mas na verdade não funcionará. Dessa forma, criará uma nova instância da classe AppDelegate toda vez que você a usar. É melhor usar o delegado acessível por meio do singleton sharedApplication. E no que diz respeito à sua segunda pergunta, sim, você provavelmente deseja usar uma constante. Mesmo assim, você pode estar alterando as propriedades do AppDelegate, provavelmente não irá atribuir o ponteiro a mais nada; nesse caso, não há necessidade de uma variável. Isso é completamente com você, no entanto. Faça o que se adequa às suas necessidades.
Mick MacCallum
2
Excelente conselho! Por engano, pensei que AppDelegate () era único, mas depois de pensar no que você disse, percebi que, se fosse, não haveria um padrão de aplicativo compartilhado para usarmos dessa maneira. É claro que não quero gerar instâncias desnecessárias, se não for necessário, para que sua declaração constante sirva perfeitamente; Obrigado.
zacjordaan
4
Não quero adicionar isso como resposta separada, mas para obter o AppDelegate com seus próprios métodos, propriedades no projeto em que são usados ​​um Swift e um Obj-c. Você deve adicionar #import "AppDelegate.h" a "ProjectName-BridgingHeader .h "
Marcin Mierzejewski
44

Swift 4.2

No Swift, fácil acesso nos VCs

extension UIViewController {
    var appDelegate: AppDelegate {
    return UIApplication.shared.delegate as! AppDelegate
   }
}
CãoCafé
fonte
26

Construtores de conveniência

Adicionar na classe AppDelegate no final do código

Swift 5

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

Para usar a referência AppDelegate em sua classe?


Chamar o método AppDelegate

appDelegate (). setRoot ()

AiOsN
fonte
Seria ótimo explicar o que setRoot () faz e quando chamá-lo. por exemplo, está tudo bem chamá-lo de um ViewController? Em um teste de unidade em que a janela ainda não está definida? Mais contexto seria ótimo.
Houman
@Houman setRoot é um método do AppDelegate que pode ser usado para alternar entre várias raízes ou ParentViewController e pode ser qualquer método. A discussão é sobre como obter a referência do AppDelegate para acesso adicional, mas espero que o setRoot também seja claro.
27419 AiOsN
19

É praticamente o mesmo que no Objective-C

let del = UIApplication.sharedApplication().delegate
Connor
fonte
19

Isso pode ser usado para o OS X

let appDelegate = NSApplication.sharedApplication().delegate as AppDelegate
var managedObjectContext = appDelegate.managedObjectContext?
jiminybob99
fonte
3
Ou simplesmentelet appDelegate = NSApp.delegate as AppDelegate
Vladimir Prudnikov 28/06
1
Em Swift 3 uselet appDelegate = NSApplication.shared().delegate as AppDelegate
Dirk
4
Em Swift 4 :NSApp.delegate as? AppDelegate
Nick
12

Aqui está a versão Swift 2.0:

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

E para acessar o contexto do objeto gerenciado:

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

        let moc = delegate.managedObjectContext

        // your code here

    }

ou, usando guarda:

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

    let moc = delegate.managedObjectContext

    // your code here
Paul Ardeleanu
fonte
10

SWIFT <3

Crie um método na classe AppDelegate para ex

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

e chamá-lo em algum outro lugar para ex

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

SWIFT> = 3.0

func sharedInstance() -> AppDelegate{
    return UIApplication.shared.delegate as! AppDelegate
}
Dharmbir Singh
fonte
2
isso também funciona, e eu gosto da ideia da nomeação sharedInstance. obrigado!
John Griffiths
2
Seu exemplo ainda instanciar um novo AppDelegateobjeto de cada vez que você ligouAppDelegate().sharedInstance()
pxpgraphics
1
Eu gosto mais desta solução do que a solução aceita (que é "sem sentido", se você precisar usá-la toda). Eu estava pensando em experimentar um extensionfor NSApplicationantes de encontrar essa resposta, mas isso é muito melhor. Atualmente, você provavelmente desejaria usar uma propriedade somente leitura de classe shared, talvez você queira publicar uma atualização para o Swift 3?
Patru 25/05
1
Na verdade, estou refatorando meu código para usar, o static var shared : TournamentDelegate? { get { return NSApplication.shared().delegate as? TournamentDelegate } }que está mais de acordo com o estilo Swift 3 em desenvolvimento de usar propriedades computadas somente leitura para esse tipo de coisa. Provavelmente poderei largar a ?vez que a refatoração estiver concluída, você não acha? (Desculpe, formatação de código em comentários é sempre uma bagunça.)
Patru
@ pxpgraphics O UIApplication é uma classe singleton, portanto, não é necessário se preocupar com instanciações múltiplas.
Abhijith 4/17/17
10

Além do que é dito aqui, no meu caso, perdi a importação do UIKit:

import UIKit
Javier Calatrava Llavería
fonte
6

Tente simplesmente o seguinte:

Swift 4

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

onde no seu AppDelegate:

// MARK: - Whatever
func whateverWillOccur() {

    // Your code here.

}

fonte
5

Aqui está uma extensão UIApplicationDelegateque evita a codificação do AppDelegatenome da 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
nyg
fonte
no Mac por NSApplicationDelegateisso me dá: 'Self' is only available in a protocol or as the result of a method in a class; did you mean 'AppDelegate'?. Isso está desatualizado?
Pkamb #
@pkamb Acabei de experimentar em um novo projeto e não tenho esse erro. Eu substituí UIApplicationDelegatepor NSApplicationDelegatee UIApplicationpor NSApplication.
Nyg 07/11/19
5
  1. Assegure-se de que você import UIKit

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

Sachin Nikumbh
fonte
4

É muito simples

Instância de delegação de aplicativo

let app = UIApplication.shared.delegate as! AppDelegate

você pode chamar um método com sintaxe de uma linha

app.callingMethod()

você pode acessar uma variável com este código

app.yourVariable = "Assigning a value"
Harendra Tiwari
fonte
2

No meu caso, estava faltando import UIKitem cima da minha NSManagedObjectsubclasse. Depois de importá-lo, eu poderia remover esse erro, como UIApplicationfaz parte doUIKit

Espero que ajude os outros !!!

NSPratik
fonte
2

Eu uso isso no Swift 2.3.

1. na classe AppDelegate

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

2.Call AppDelegate com

let appDelegate = AppDelegate.sharedInstance
Ted Liu
fonte
2
extension AppDelegate {

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

A partir do iOS 12.2 e Swift 5.0, AppDelegatenão é um símbolo reconhecido. UIApplicationDelegateé. Quaisquer respostas referentes a, AppDelegateportanto, não estão mais corretas. A resposta a seguir está correta e evita o desempacotamento forçado, que alguns desenvolvedores consideram um cheiro de código:

import UIKit

extension UIViewController {
  var appDelegate: UIApplicationDelegate {
    guard let appDelegate = UIApplication.shared.delegate else {
      fatalError("Could not determine appDelegate.")
    }
    return appDelegate
  }
}
Josh Adams
fonte
1
No swift5, seu código exibirá o aviso "UIApplication.delegate deve ser usado apenas no thread principal". Você pode atualizar a resposta.
Mahesh Narla
isso fatalErroré funcionalmente equivalente a uma força desembrulhada!
pkamb 5/11/19
1

No Swift 3.0, você pode obter a appdelegatereferência por

let appDelegate = UIApplication.shared.delegate as! AppDelegate
Ramakrishna
fonte
0

No Xcode 6.2, isso também funciona

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

let aVariable = appDelegate.someVariable
v01d
fonte
2
v01d, de onde você tirou isso?
NSPratik