Wie erhalte ich einen Verweis auf den App-Delegaten in Swift?

409

Wie erhalte ich einen Verweis auf den App-Delegaten in Swift?

Letztendlich möchte ich die Referenz verwenden, um auf den Kontext des verwalteten Objekts zuzugreifen.

AperioOculus
quelle
8
Beachten Sie, dass einige die Verwendung des App-Delegaten als Container für den verwalteten Objektkontext oder andere "globale" Objekte als Anti-Pattern betrachten würden. Lassen Sie den App-Delegaten den MOC an den Controller übergeben, anstatt ihn vom Controller finden zu lassen.
Kristopher Johnson
1
@KristopherJohnson Hey Kris, wie kann ich das Einfügen von Abhängigkeiten in Ansichtscontroller durch AppDelegate vereinfachen? Instanziieren Sie den View Controller programmgesteuert und verwenden Sie die Reflexion, um zu entscheiden, was rekursiv instanziiert / injiziert werden soll. Gibt es Frameworks, die dabei helfen können? Wenn ich dies für jeden View Controller manuell tun muss, wird mein AppDelegate riesig! Oh, am besten ohne eine Fabrik für alles zu schaffen :)
Jimbo
1
Eine flüchtige Suche fand Swinject, das auch automatische Verkabelung hat :)
Jimbo
6
Für Programmierer , die gegen Putting etwas „fremden“ in der App Delegierten beraten, ist es ein Unsinn Bit , weil der Apple - Dokumentation ausdrücklich , dass eine "crucial role"der UIApplicationDelegateSingleton ist "...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

Antworten:

756

Die andere Lösung ist insofern korrekt, als Sie einen Verweis auf den Delegaten der Anwendung erhalten. Auf diese Weise können Sie jedoch nicht auf Methoden oder Variablen zugreifen, die von Ihrer UIApplication-Unterklasse hinzugefügt wurden, wie z. B. Ihren verwalteten Objektkontext. Um dies zu beheben, senden Sie einfach einen Downcast auf "AppDelegate" oder wie auch immer Ihre UIApplication-Unterklasse aufgerufen wird. In Swift 3, 4 & 5 wird dies wie folgt durchgeführt:

let appDelegate = UIApplication.shared.delegate as! AppDelegate
let aVariable = appDelegate.someVariable
Mick MacCallum
quelle
10
Falls immer noch Probleme auftreten, müssen Sie für das Targeting von OS X Cocoa importieren, damit dies für NSApplication.sharedApplication () funktioniert. Ich würde vermuten, dass iOS das Äquivalent benötigen würde.
Smaurice
2
Dies ist die nützlichere der beiden Antworten.
Joe
3
@zacjordaan Mit dieser Methode erhalten Sie eine automatische Vervollständigung für die Eigenschaft, die jedoch nicht funktioniert. Auf diese Weise wird bei jeder Verwendung eine neue Instanz der AppDelegate-Klasse erstellt. Verwenden Sie besser den Delegaten, auf den Sie über den Singleton "sharedApplication" zugreifen können. Und was Ihre zweite Frage betrifft, möchten Sie wahrscheinlich eine Konstante verwenden. Auch wenn Sie möglicherweise die Eigenschaften von AppDelegate ändern, werden Sie den Zeiger wahrscheinlich nicht neu zuweisen. In diesem Fall ist keine Variable erforderlich. Dies liegt jedoch ganz bei Ihnen. Tun Sie, was Ihren Bedürfnissen entspricht.
Mick MacCallum
2
Exzellenter Rat! Ich hatte fälschlicherweise gedacht, dass AppDelegate () Singleton ist, aber nachdem ich über das nachgedacht habe, was Sie gesagt haben, habe ich festgestellt, dass es in diesem Fall kein SharedApplication-Muster geben würde, das wir auf diese Weise verwenden könnten. Natürlich möchte ich keine unnötigen Instanzen erzeugen, wenn ich nicht muss, daher wird Ihre ständige Erklärung perfekt passen. Vielen Dank.
Zacjordaan
4
Ich möchte dies nicht als separate Antwort hinzufügen, aber um AppDelegate mit Ihren eigenen Methoden und Eigenschaften in einem Projekt zu erhalten, in dem sowohl ein Swift als auch ein Obj-c verwendet werden, sollten Sie #import "AppDelegate.h" zu "ProjectName-BridgingHeader" hinzufügen .h "
Marcin Mierzejewski
44

Swift 4.2

In Swift einfach in Ihren VCs zuzugreifen

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

Convenience-Konstruktoren

Fügen Sie die AppDelegate-Klasse am Ende des Codes hinzu

Swift 5

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

So verwenden Sie die AppDelegate-Referenz in Ihrer Klasse?


Rufen Sie die AppDelegate-Methode auf

appDelegate (). setRoot ()

AiOsN
quelle
Es wäre toll zu erklären, was setRoot () macht und wann es aufgerufen werden soll. Ist es beispielsweise in Ordnung, es von einem ViewController aus aufzurufen? Aus einem Unit-Test, bei dem das Fenster noch nicht eingestellt ist? Mehr Kontext wäre toll.
Houman
@Houman setRoot ist eine Methode von AppDelegate, mit der zwischen mehreren Roots oder ParentViewController gewechselt werden kann und die eine beliebige Methode sein kann. In der Diskussion geht es darum, wie die Referenz von AppDelegate für den weiteren Zugriff verwendet werden kann, aber hoffentlich muss auch setRoot klar sein.
AiOsN
19

Es ist so ziemlich das gleiche wie in Objective-C

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

Dies könnte für OS X verwendet werden

let appDelegate = NSApplication.sharedApplication().delegate as AppDelegate
var managedObjectContext = appDelegate.managedObjectContext?
jiminybob99
quelle
3
Oder einfachlet appDelegate = NSApp.delegate as AppDelegate
Vladimir Prudnikov
1
In Swift 3 verwendenlet appDelegate = NSApplication.shared().delegate as AppDelegate
Dirk
4
In Swift 4 :NSApp.delegate as? AppDelegate
Nick
12

Hier ist die Swift 2.0-Version:

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

Und um auf den Kontext des verwalteten Objekts zuzugreifen:

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

        let moc = delegate.managedObjectContext

        // your code here

    }

oder mit Wache:

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

    let moc = delegate.managedObjectContext

    // your code here
Paul Ardeleanu
quelle
10

SWIFT <3

Erstellen Sie beispielsweise eine Methode in der AppDelegate-Klasse

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

und nenne es woanders zum Beispiel

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

SWIFT> = 3.0

func sharedInstance() -> AppDelegate{
    return UIApplication.shared.delegate as! AppDelegate
}
Dharmbir Singh
quelle
2
Dies funktioniert auch und ich mag die Idee der SharedInstance-Benennung. Vielen Dank!
John Griffiths
2
Ihr Beispiel würde immer noch ein neues AppDelegateObjekt instanziieren, wenn Sie AppDelegate().sharedInstance()
anrufen
1
Ich mag diese Lösung besser als die akzeptierte (die "unsiwftly" ausführlich ist, wenn Sie sie überall verwenden müssen). Ich habe darüber nachgedacht, mit einem extensionfor zu experimentieren, NSApplicationbevor ich diese Antwort gefunden habe, aber das ist viel besser. Heutzutage möchten Sie wahrscheinlich eine klassenberechnete schreibgeschützte Eigenschaft verwenden shared. Vielleicht möchten Sie ein Update für Swift 3 veröffentlichen?
Patru
1
Ich bin gerade dabei, meinen Code für die Verwendung umzugestalten, static var shared : TournamentDelegate? { get { return NSApplication.shared().delegate as? TournamentDelegate } }was eher dem sich entwickelnden Swift 3-Stil entspricht, berechnete schreibgeschützte Eigenschaften für diese Art von Dingen zu verwenden. Ich werde das wahrscheinlich fallen lassen können, ?sobald das Refactoring abgeschlossen ist, meinst du nicht auch? (Sorry, Code-Formatierung in Kommentaren ist immer ein Chaos.)
Patru
@ pxpgraphics UIApplication ist eine Singleton-Klasse, sodass Sie sich keine Gedanken über die mehrfache Instanziierung machen müssen.
Abhijith
10

Abgesehen von dem, was hier gesagt wird, habe ich in meinem Fall den Import von UIKit verpasst:

import UIKit
Javier Calatrava Llavería
quelle
6

Versuchen Sie einfach Folgendes:

Swift 4

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

Wo in Ihrem AppDelegate:

// MARK: - Whatever
func whateverWillOccur() {

    // Your code here.

}

quelle
5

Hier ist eine Erweiterung UIApplicationDelegate, die das Hardcodieren des AppDelegateKlassennamens vermeidet :

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
quelle
auf dem Mac NSApplicationDelegatedafür gibt mir : 'Self' is only available in a protocol or as the result of a method in a class; did you mean 'AppDelegate'?. Ist das veraltet?
Pkamb
@pkamb Ich habe es gerade in einem neuen Projekt versucht und ich habe diesen Fehler nicht. Ich habe UIApplicationDelegatenach NSApplicationDelegateund UIApplicationnach ersetzt NSApplication.
Nyg
5
  1. Stell sicher, dass du import UIKit

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

Sachin Nikumbh
quelle
4

es ist sehr einfach

App-Delegateninstanz

let app = UIApplication.shared.delegate as! AppDelegate

Sie können eine Methode mit einzeiliger Syntax aufrufen

app.callingMethod()

Mit diesem Code können Sie auf eine Variable zugreifen

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

In meinem Fall fehlte ich import UIKitoben in meiner NSManagedObjectUnterklasse. Nach dem Import konnte ich diesen Fehler wie UIApplicationder Teil von entfernenUIKit

Hoffe es hilft anderen !!!

NSPratik
quelle
2

Ich benutze dies in Swift 2.3.

1.in AppDelegate-Klasse

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

2. Rufen Sie AppDelegate mit an

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

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

Ab iOS 12.2 und Swift 5.0 AppDelegateist kein Symbol anerkannt. UIApplicationDelegateist. Alle Antworten, auf die Bezug genommen wird, AppDelegatesind daher nicht mehr korrekt. Die folgende Antwort ist richtig und vermeidet das gewaltsame Auspacken, das einige Entwickler als Codegeruch betrachten:

import UIKit

extension UIViewController {
  var appDelegate: UIApplicationDelegate {
    guard let appDelegate = UIApplication.shared.delegate else {
      fatalError("Could not determine appDelegate.")
    }
    return appDelegate
  }
}
Josh Adams
quelle
1
In swift5 gibt Ihr Code die Warnung "UIApplication.delegate darf nur vom Hauptthread verwendet werden" aus. Können Sie die Antwort aktualisieren?
Mahesh Narla
das fatalErrorentspricht funktional einer Kraft zum Auspacken!
Pkamb
1

In Swift 3.0 können Sie die appdelegateReferenz von erhalten

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

Im Xcode 6.2 funktioniert dies auch

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

let aVariable = appDelegate.someVariable
v01d
quelle
2
v01d, woher hast du das genommen?
NSPratik