Bagaimana cara mendapatkan referensi ke delegasi aplikasi di Swift?

409

Bagaimana cara mendapatkan referensi ke delegasi aplikasi di Swift?

Pada akhirnya, saya ingin menggunakan referensi untuk mengakses konteks objek yang dikelola.

AperioOculus
sumber
8
Perhatikan bahwa beberapa orang akan menganggap penggunaan delegasi aplikasi sebagai wadah untuk konteks objek yang dikelola atau objek "global" lainnya sebagai anti-pola. Pertimbangkan meminta delegasi aplikasi meneruskan MOC ke controller, daripada membuat controller menemukannya.
Kristopher Johnson
1
@KristopherJohnson Hei Kris, bagaimana saya bisa memfasilitasi ketergantungan AppDelegate menyuntikkan ke pengontrol tampilan? Instantiate tampilan controller secara terprogram dan gunakan refleksi untuk memutuskan apa yang akan instantiate / menyuntikkan, secara rekursif? Apakah ada kerangka kerja yang dapat membantu dengan ini? Jika saya harus melakukan ini untuk setiap pengontrol tampilan secara manual, AppDelegate saya akan menjadi sangat besar! Oh, lebih baik tanpa membuat pabrik untuk semuanya :)
Jimbo
1
Pencarian sepintas menemukan Swinject yang juga memiliki auto-wiring :)
Jimbo
6
Untuk programmer yang menyarankan untuk tidak memasukkan sesuatu yang "asing" dalam delegasi aplikasi, itu sedikit omong kosong karena dokumentasi Apple secara eksplisit menyatakan bahwa salah "crucial role"satu UIApplicationDelegatesingleton adalah "...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

Jawaban:

757

Solusi lain benar karena akan memberi Anda referensi ke delegasi aplikasi, tetapi ini tidak akan memungkinkan Anda untuk mengakses metode atau variabel apa pun yang ditambahkan oleh subkelas aplikasi UIA, seperti konteks objek terkelola. Untuk mengatasinya, cukup turunkan ke "AppDelegate" atau apa pun subkelas aplikasi UIA Anda yang dipanggil. Dalam Swift 3, 4 & 5 , ini dilakukan sebagai berikut:

let appDelegate = UIApplication.shared.delegate as! AppDelegate
let aVariable = appDelegate.someVariable
Mick MacCallum
sumber
10
Jika ada yang masih mengalami masalah, penargetan OS X mengharuskan Anda untuk mengimpor Kakao agar ini berfungsi untuk NSApplication. SharedApplication (). Saya kira iOS akan membutuhkan yang setara.
smaurice
2
Ini lebih berguna dari dua jawaban.
Joe
3
@zacjordaan Menggunakan metode itu, Anda akan mendapatkan pelengkapan otomatis untuk properti, tetapi itu tidak akan benar-benar berfungsi. Dengan begitu akan membuat instance baru dari kelas AppDelegate setiap kali Anda menggunakannya. Anda lebih baik menggunakan delegasi yang dapat diakses melalui singleton Aplikasi bersama. Dan sejauh pertanyaan kedua Anda, ya, Anda mungkin ingin menggunakan konstanta. Meskipun, Anda mungkin mengubah properti AppDelegate, Anda mungkin tidak akan menetapkan ulang pointer ke hal lain, dalam hal ini, tidak perlu variabel. Ini sepenuhnya terserah Anda sekalipun. Lakukan apa yang sesuai dengan kebutuhan Anda.
Mick MacCallum
2
Saran yang sangat baik! Saya keliru mengira bahwa AppDelegate () adalah singleton tetapi setelah memikirkan apa yang Anda katakan, saya menyadari bahwa jika itu terjadi maka tidak akan ada pola Aplikasi bersama untuk kita gunakan dengan cara ini. Tentu saja saya tidak ingin menelurkan contoh yang tidak perlu jika saya tidak perlu, sehingga deklarasi konstan Anda akan cocok dengan sempurna; Terima kasih.
zacjordaan
4
Saya tidak ingin menambahkan ini sebagai jawaban terpisah, tetapi untuk mendapatkan AppDelegate dengan metode Anda sendiri, properti di proyek tempat Swift dan Obj-c digunakan. Anda harus menambahkan #import "AppDelegate.h" ke "ProjectName-BridgingHeader .h "
Marcin Mierzejewski
44

Cepat 4.2

Di Swift, mudah diakses di VC Anda

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

Konstruktor Kenyamanan

Tambahkan Kelas AppDelegate di akhir kode

Cepat 5

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

Untuk menggunakan referensi AppDelegate di kelas Anda?


Panggil Metode AppDelegate

appDelegate (). setRoot ()

AiOsN
sumber
Akan bagus untuk menjelaskan apa yang dilakukan setRoot () dan kapan harus memanggilnya. misalnya apakah boleh memanggilnya dari ViewController? Dari tes Unit di mana jendela belum diatur? Lebih banyak konteks akan lebih bagus.
Houman
@Houman setRoot adalah metode dari AppDelegate yang dapat digunakan untuk beralih di antara banyak Roots atau ParentViewController dan bisa berupa metode apa pun. Diskusi adalah tentang cara mendapatkan referensi AppDelegate untuk akses lebih lanjut, tetapi berharap setRoot juga harus jelas.
AiOsN
19

Ini hampir sama dengan di Objective-C

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

Ini dapat digunakan untuk OS X

let appDelegate = NSApplication.sharedApplication().delegate as AppDelegate
var managedObjectContext = appDelegate.managedObjectContext?
jiminybob99
sumber
3
Atau sederhananyalet appDelegate = NSApp.delegate as AppDelegate
Vladimir Prudnikov
1
Dalam Swift 3 penggunaanlet appDelegate = NSApplication.shared().delegate as AppDelegate
Dirk
4
Dalam Swift 4 :NSApp.delegate as? AppDelegate
Nick
12

Berikut adalah versi Swift 2.0:

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

Dan untuk mengakses konteks objek yang dikelola:

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

        let moc = delegate.managedObjectContext

        // your code here

    }

atau, menggunakan pelindung:

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

    let moc = delegate.managedObjectContext

    // your code here
Paul Ardeleanu
sumber
10

SWIFT <3

Buat metode di Kelas AppDelegate untuk ex

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

dan menyebutnya beberapa tempat lain untuk mantan

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

SWIFT> = 3.0

func sharedInstance() -> AppDelegate{
    return UIApplication.shared.delegate as! AppDelegate
}
Dharmbir Singh
sumber
2
ini juga berfungsi, dan saya suka gagasan penamaan sharedInstance. Terima kasih!
John Griffiths
2
Contoh Anda masih akan instantiate AppDelegateobjek baru setiap kali Anda meneleponAppDelegate().sharedInstance()
pxpgraphics
1
Saya suka solusi ini lebih baik daripada yang diterima (yang "unsiwftly" verbose jika Anda harus menggunakannya di seluruh). Saya sedang berpikir tentang bereksperimen dengan extensionuntuk NSApplicationsebelum saya menemukan jawaban ini, tetapi ini jauh lebih baik. Namun saat ini Anda mungkin ingin menggunakan properti read only yang dikomputasi dengan kelas shared, mungkin Anda ingin memposting pembaruan untuk Swift 3?
Patru
1
Saya sebenarnya dalam proses refactoring kode saya untuk menggunakan static var shared : TournamentDelegate? { get { return NSApplication.shared().delegate as? TournamentDelegate } }yang lebih sejalan dengan pengembangan gaya Swift 3 menggunakan properti read only untuk jenis hal-hal ini. Saya mungkin akan bisa drop ?setelah refactoring selesai, bukan begitu? (Maaf, pemformatan kode dalam komentar selalu berantakan.)
Patru
@ pxpgraphics UIApplication adalah kelas tunggal sehingga tidak perlu khawatir tentang banyak instance.
Abhijith
10

Appart dari apa yang diceritakan di sini, dalam kasus saya, saya melewatkan impor UIKit:

import UIKit
Javier Calatrava Llavería
sumber
6

Coba ini saja:

Cepat 4

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

di mana di AppDelegate Anda:

// MARK: - Whatever
func whateverWillOccur() {

    // Your code here.

}

sumber
5

Berikut ini ekstensi untuk UIApplicationDelegateyang menghindari pengodean AppDelegatenama kelas:

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
sumber
pada Mac untuk NSApplicationDelegateini memberi saya: 'Self' is only available in a protocol or as the result of a method in a class; did you mean 'AppDelegate'?. Apakah ini ketinggalan jaman?
pkamb
@ pkamb Saya baru saja mencobanya di proyek baru dan saya tidak memiliki kesalahan ini. Saya digantikan UIApplicationDelegateoleh NSApplicationDelegatedan UIApplicationoleh NSApplication.
Nyg
5
  1. Pastikan Anda import UIKit

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

Sachin Nikumbh
sumber
4

ini sangat sederhana

Contoh delegasi aplikasi

let app = UIApplication.shared.delegate as! AppDelegate

Anda dapat memanggil metode dengan sintaksis satu baris

app.callingMethod()

Anda dapat mengakses variabel dengan kode ini

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

Dalam kasus saya, saya hilang import UIKitdi atas NSManagedObjectsubkelas saya . Setelah mengimpornya, saya bisa menghapus kesalahan itu sebagaimana UIApplicationbagian dariUIKit

Semoga ini bisa membantu orang lain !!!

NSPratik
sumber
2

Saya menggunakan ini di Swift 2.3.

1. di kelas AppDelegate

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

2. Hubungi AppDelegate dengan

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

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

Pada iOS 12.2 dan Swift 5.0, AppDelegatebukan simbol yang dikenali. UIApplicationDelegateadalah. AppDelegateKarenanya, jawaban yang merujuk tidak lagi benar. Jawaban berikut ini benar dan menghindari pembatalan paksa, yang oleh beberapa pengembang dianggap sebagai bau kode:

import UIKit

extension UIViewController {
  var appDelegate: UIApplicationDelegate {
    guard let appDelegate = UIApplication.shared.delegate else {
      fatalError("Could not determine appDelegate.")
    }
    return appDelegate
  }
}
Josh Adams
sumber
1
Di swift5 kode Anda akan memberikan peringatan "UIApplication.delegate harus digunakan dari utas utama saja". Bisakah Anda memperbarui jawaban.
Mahesh Narla
yang fatalErrorsecara fungsional setara dengan kekuatan yang terbuka!
pkamb
1

Di Swift 3.0 Anda bisa mendapatkan appdelegatereferensi dengan

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

Dalam Xcode 6.2, ini juga berfungsi

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

let aVariable = appDelegate.someVariable
v01d
sumber
2
v01d, dari mana Anda mengambil itu?
NSPratik