Jak uzyskać odniesienie do delegata aplikacji w Swift?

409

Jak uzyskać odniesienie do delegata aplikacji w Swift?

Ostatecznie chcę użyć odwołania, aby uzyskać dostęp do kontekstu obiektu zarządzanego.

AperioOculus
źródło
8
Zauważ, że niektórzy uznaliby użycie delegacji aplikacji jako kontenera kontekstu obiektów zarządzanych lub innych „globalnych” obiektów za anty-wzorek. Zastanów się, czy delegat aplikacji przekazuje MOC do kontrolera, zamiast sprawić, by kontroler go znalazł.
Kristopher Johnson
1
@KristopherJohnson Hej Kris, jak mogę ułatwić wprowadzanie zależności AppDelegate do kontrolerów widoku? Utwórz programowo kontroler widoku i użyj odbicia, aby zdecydować, co utworzyć / wprowadzić, rekurencyjnie? Czy są jakieś ramy, które mogą w tym pomóc? Jeśli muszę to zrobić ręcznie dla każdego kontrolera widoku, moja AppDelegate będzie ogromna! Och, najlepiej bez tworzenia fabryki wszystkiego :)
Jimbo
1
Pobieżne wyszukiwanie znalazło Swinject, który ma również automatyczne okablowanie :)
Jimbo
6
Dla programistów, którzy odradzają umieszczanie czegokolwiek „obcego” w delegacie aplikacji, to trochę nonsens, ponieważ dokumentacja Apple wyraźnie stwierdza, że ​​jednym "crucial role"z UIApplicationDelegatesingletonów jest "...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

Odpowiedzi:

757

Drugie rozwiązanie jest poprawne, ponieważ zawiera odniesienie do delegata aplikacji, ale nie pozwoli ci uzyskać dostępu do żadnych metod lub zmiennych dodanych przez twoją podklasę UIApplication, takich jak kontekst obiektu zarządzanego. Aby rozwiązać ten problem, po prostu przejdź do „AppDelegate” lub jakkolwiek kiedykolwiek wywoływana jest twoja podklasa UIApplication. W Swift 3, 4 i 5 odbywa się to w następujący sposób:

let appDelegate = UIApplication.shared.delegate as! AppDelegate
let aVariable = appDelegate.someVariable
Mick MacCallum
źródło
10
W przypadku, gdy ktoś nadal ma problemy, celowanie w system OS X wymaga zaimportowania kakao, aby działało to w przypadku NSApplication.sharedApplication (). Sądzę, że iOS potrzebowałby odpowiednika.
smaurice
2
Jest to bardziej przydatne z dwóch odpowiedzi.
Joe
3
@zacjordaan Za pomocą tej metody otrzymasz autouzupełnianie właściwości, ale tak naprawdę nie zadziała. W ten sposób utworzysz nową instancję klasy AppDelegate za każdym razem, gdy z niej korzystasz. Lepiej skorzystaj z delegata dostępnego przez singleton sharedApplication. A jeśli chodzi o twoje drugie pytanie, tak, prawdopodobnie chcesz użyć stałej. Chociaż możesz zmieniać właściwości AppDelegate, prawdopodobnie nie będziesz ponownie przypisywać wskaźnika do niczego innego, w którym to przypadku nie potrzebujesz zmiennej. To zależy wyłącznie od Ciebie. Rób to, co odpowiada Twoim potrzebom.
Mick MacCallum
2
Doskonała rada! Pomyślałem, że AppDelegate () jest singletonem, ale po przemyśleniu tego, co powiedziałeś, zdałem sobie sprawę, że gdyby tak było, nie byłoby wspólnego wzorca aplikacji, którego moglibyśmy używać w ten sposób. Oczywiście nie chcę odradzać niepotrzebnych instancji, jeśli nie muszę, więc twoja stała deklaracja będzie idealnie pasować; Dziękuję Ci.
zacjordaan
4
Nie chcę dodawać tego jako osobnej odpowiedzi, ale aby uzyskać AppDelegate własnymi metodami, właściwościami w projekcie, w których używane są zarówno Swift, jak i Obj-c, należy dodać #import „AppDelegate.h” do „ProjectName-BridgingHeader .h "
Marcin Mierzejewski
44

Szybki 4.2

W Swift, łatwy dostęp w VC

extension UIViewController {
    var appDelegate: AppDelegate {
    return UIApplication.shared.delegate as! AppDelegate
   }
}
DogCoffee
źródło
25

Konstruktorzy wygody

Dodaj klasę AppDelegate na końcu kodu

Szybki 5

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

Aby użyć odwołania AppDelegate w swojej klasie?


Wywołaj metodę AppDelegate

appDelegate (). setRoot ()

AiOsN
źródło
Byłoby wspaniale wyjaśnić, co robi setRoot () i kiedy go wywołać. np. czy można zadzwonić z ViewController? Z testu jednostkowego, w którym okno nie jest jeszcze ustawione? Większy kontekst byłby świetny.
Houman
@Houman setRoot to metoda AppDelegate, która może być używana do przełączania między wieloma Rootami lub ParentViewController i może być dowolną metodą. Dyskusja dotyczy sposobu uzyskania odniesienia do AppDelegate w celu uzyskania dalszego dostępu, ale nadzieja setRoot również musi być jasna.
AiOsN
19

Jest prawie taki sam jak w Objective-C

let del = UIApplication.sharedApplication().delegate
Connor
źródło
19

Można to wykorzystać w systemie OS X.

let appDelegate = NSApplication.sharedApplication().delegate as AppDelegate
var managedObjectContext = appDelegate.managedObjectContext?
jiminybob99
źródło
3
Lub po prostulet appDelegate = NSApp.delegate as AppDelegate
Vladimir Prudnikov,
1
W Swift 3 użyjlet appDelegate = NSApplication.shared().delegate as AppDelegate
Dirk
4
W Swift 4 :NSApp.delegate as? AppDelegate
Nick
12

Oto wersja Swift 2.0:

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

Aby uzyskać dostęp do kontekstu obiektu zarządzanego:

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

        let moc = delegate.managedObjectContext

        // your code here

    }

lub przy użyciu wartownika:

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

    let moc = delegate.managedObjectContext

    // your code here
Paul Ardeleanu
źródło
10

SWIFT <3

Utwórz metodę w klasie AppDelegate np

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

i nazwać to gdzie indziej na przykład

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

SWIFT> = 3,0

func sharedInstance() -> AppDelegate{
    return UIApplication.shared.delegate as! AppDelegate
}
Dharmbir Singh
źródło
2
to również działa i podoba mi się pomysł nazewnictwa sharedInstance. dzięki!
John Griffiths,
2
Twój przykład wciąż AppDelegateAppDelegate().sharedInstance()
tworzyłby
1
Podoba mi się to rozwiązanie bardziej niż zaakceptowane (które jest „niezachwiane” pełne, jeśli musisz z niego korzystać cały czas). Myślałam o eksperymentowanie ze związkiem extensiono NSApplicationzanim znalazłem tę odpowiedź, ale jest to o wiele lepiej. W dzisiejszych czasach prawdopodobnie chciałbyś skorzystać z klasy obliczonej właściwości tylko do odczytu shared, może chcesz opublikować aktualizację do Swift 3?
Patru
1
W rzeczywistości jestem w trakcie refaktoryzacji mojego kodu, static var shared : TournamentDelegate? { get { return NSApplication.shared().delegate as? TournamentDelegate } }który jest bardziej zgodny z rozwijającym się stylem Swift 3 polegającym na stosowaniu obliczonych właściwości tylko do odczytu dla tego typu rzeczy. Prawdopodobnie będę w stanie zrezygnować ?po zakończeniu refaktoryzacji, nie sądzisz? (Przepraszamy, formatowanie kodu w komentarzach jest zawsze bałaganem.)
Patru
@ pxpgraphics UIApplication jest klasą singletonową, więc nie musisz się martwić o wielokrotne tworzenie instancji.
Abhijith,
10

Apart z tego, co tu powiedziano, w moim przypadku przegapiłem import UIKit:

import UIKit
Javier Calatrava Llavería
źródło
6

Spróbuj po prostu tego:

Szybki 4

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

gdzie w Twojej aplikacjiDelegate:

// MARK: - Whatever
func whateverWillOccur() {

    // Your code here.

}

źródło
5

Oto rozszerzenie pozwalające UIApplicationDelegateuniknąć twardego wpisania AppDelegatenazwy klasy:

extension UIApplicationDelegate {

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

// use like this:
let appDelegate = MyAppDelegate.shared // will be of type MyAppDelegate
Nig
źródło
na Mac za NSApplicationDelegateto daje mi: 'Self' is only available in a protocol or as the result of a method in a class; did you mean 'AppDelegate'?. Czy to jest przestarzałe?
pkamb
@pkamb Właśnie wypróbowałem to w nowym projekcie i nie mam tego błędu. Wymieniłem UIApplicationDelegateprzez NSApplicationDelegatei UIApplicationprzez NSApplication.
nyg
5
  1. Upewnij się, że import UIKit

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

Sachin Nikumbh
źródło
4

to bardzo proste

Instancja delegowania aplikacji

let app = UIApplication.shared.delegate as! AppDelegate

możesz wywołać metodę z jedną składnią wiersza

app.callingMethod()

możesz uzyskać dostęp do zmiennej za pomocą tego kodu

app.yourVariable = "Assigning a value"
Harendra Tiwari
źródło
2

W moim przypadku brakowało mi import UIKitna szczycie mojej NSManagedObjectpodklasy. Po zaimportowaniu mógłbym usunąć ten błąd, tak jak UIApplicationjest to w przypadkuUIKit

Mam nadzieję, że pomaga innym !!!

NSPratik
źródło
2

Używam tego w Swift 2.3.

1. w klasie AppDelegate

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

2. Zadzwoń z AppDelegate za pomocą

let appDelegate = AppDelegate.sharedInstance
Ted Liu
źródło
2
extension AppDelegate {

    // MARK: - App Delegate Ref
    class func delegate() -> AppDelegate {
        return UIApplication.shared.delegate as! AppDelegate
    }
}
CrazyPro007
źródło
2

Począwszy od iOS 12.2 i Swift 5.0, AppDelegatenie jest rozpoznawalnym symbolem. UIApplicationDelegatejest. Wszelkie odnośne odpowiedzi AppDelegatenie są już poprawne. Poniższa odpowiedź jest poprawna i pozwala uniknąć rozpakowywania wymuszonego, które niektórzy programiści uważają za zapach kodu:

import UIKit

extension UIViewController {
  var appDelegate: UIApplicationDelegate {
    guard let appDelegate = UIApplication.shared.delegate else {
      fatalError("Could not determine appDelegate.")
    }
    return appDelegate
  }
}
Josh Adams
źródło
1
W swift5 Twój kod wyświetli ostrzeżenie „UIApplication.delegate musi być używane tylko z głównego wątku”. Czy możesz zaktualizować odpowiedź?
Mahesh Narla,
że fatalErrorjest funkcjonalnym odpowiednikiem rozpakować siły!
pkamb
1

W Swift 3.0 możesz uzyskać appdelegatereferencję przez

let appDelegate = UIApplication.shared.delegate as! AppDelegate
Ramakrishna
źródło
0

W Xcode 6.2 to również działa

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

let aVariable = appDelegate.someVariable
v01d
źródło
2
v01d, skąd to wziąłeś?
NSPratik