Як отримати посилання на делегата програми в Swift?


409

Як отримати посилання на делегата програми в Swift?

Зрештою, я хочу використовувати посилання для доступу до контексту керованого об'єкта.


8
Зауважте, що деякі вважають використання делегата програми як контейнера для контексту керованого об'єкта чи інших "глобальних" об'єктів антидіаграмою. Подумайте, як делегат програми передає MOC контролеру, а не змушує його знайти його.
Крістофер Джонсон

1
@ KristopherJohnson Ей Крис, як я можу полегшити AppDelegate введення залежностей у контролери перегляду? Програмуйте контролер перегляду програмно та використовуйте роздуми, щоб вирішити, що інстанціювати / вводити, рекурсивно? Чи є рамки, які можуть допомогти у цьому? Якщо мені доведеться це зробити для кожного контролера перегляду вручну, мій AppDelegate буде величезним! О, бажано, не створюючи фабрику для всього :)
Jimbo

1
Короткий пошук знайшов Swinject, який також має автоматичну проводку :)
Jimbo

6
Для програмістів , які радять проти покласти що - небудь «стороннє» в додатку делегата, це трохи нонсенс , тому що документація Apple , прямо говориться про те , що "crucial role"з UIApplicationDelegateСінглтона "...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

Відповіді:


757

Інше рішення є правильним, оскільки воно отримає посилання на делегата програми, але це не дозволить отримати доступ до будь-яких методів або змінних, доданих вашим підкласом UIApplication, як у контексті керованого об'єкта. Щоб вирішити це, просто перейдіть на "AppDelegate" або те, що коли-небудь називається вашим підкласом UIApplication. У Swift 3, 4 і 5 це робиться наступним чином:

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

10
У разі, якщо у когось все ще виникають проблеми, націлювання на OS X вимагає, щоб ви імпортували какао, щоб це працювало для NSApplication.sharedApplication (). Я б здогадався, що iOS знадобиться еквівалент.
smaurice

2
Це корисніше з двох відповідей.
Джо

3
@zacjordaan Використовуючи цей метод, ви отримаєте автодоповнення для власності, але він насправді не працюватиме. Таким чином буде створюватися новий примірник класу AppDelegate кожен раз, коли ви його використовуєте. Вам краще скористатися делегатом, доступним через єдину кнопку sharedApplication. А що стосується вашого другого питання, так, ви, мабуть, хочете використовувати константу. Незважаючи на те, що, можливо, ви змінюєте властивості AppDelegate, ви, ймовірно, не будете переназначати покажчик ні на що інше, і в цьому випадку змінної немає необхідності. Це повністю залежить від вас. Робіть те, що відповідає вашим потребам.
Мік Маккаллум

2
Відмінна порада! Я помилково подумав, що AppDelegate () синглтон, але, подумавши про те, що ви сказали, я зрозумів, що якби це було тоді, не було б схеми спільного використання для нас, щоб використовувати таким чином. Звичайно, я не хочу зароджувати зайві екземпляри, якщо мені цього не доведеться, тому ваша постійна заява ідеально підійде; Дякую.
zacjordaan

4
Я не хочу додавати це як окрему відповідь, але щоб отримати AppDelegate своїми власними методами, властивостями в проекті, де використовуються і Swift, і Obj-c, слід додати #import "AppDelegate.h" до "ProjectName-BridgingHeader" .h "
Marcin

44

Швидкий 4.2

У Swift простий доступ у ваших відеокамерах

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

25

Конструктори зручності

Додайте в AppDelegate Class в кінці коду

Швидкий 5

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

Щоб використовувати посилання AppDelegate у своєму класі?


Виклик методу AppDelegate

appDelegate (). setRoot ()


Було б чудово пояснити, що робить setRoot () і коли його викликати. наприклад, це нормально називати це з ViewController? З тесту одиниці, де вікно ще не встановлено? Більше контексту було б чудово.
Houman

@Houman setRoot - це метод від AppDelegate, який може використовуватися для перемикання між декількома Roots або ParentViewController, і це може бути будь-який метод. Обговорення стосується того, як отримати посилання на AppDelegate для подальшого доступу, але сподіваємось, що setRoot також повинен бути зрозумілим.
AiOsN

19

Це майже те саме, що і в Objective-C

let del = UIApplication.sharedApplication().delegate

19

Це може бути використане для OS X

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

3
Або простоlet appDelegate = NSApp.delegate as AppDelegate
Володимир Прудніков

1
У Swift 3 використанняlet appDelegate = NSApplication.shared().delegate as AppDelegate
Дірк

4
У Свіфті 4 :NSApp.delegate as? AppDelegate
Нік

12

Ось версія Swift 2.0:

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

І щоб отримати доступ до контексту керованого об'єкта:

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

        let moc = delegate.managedObjectContext

        // your code here

    }

або, використовуючи охорону:

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

    let moc = delegate.managedObjectContext

    // your code here

10

SWIFT <3

Створіть метод у AppDelegate Class для напр

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

і назвіть це де-небудь ще, наприклад

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

SWIFT> = 3.0

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

2
це також працює, і мені подобається ідея іменування sharedInstance. Дякую!
Джон Гриффітс

2
Ваш приклад все одно буде створювати новий AppDelegateоб'єкт кожного разу, коли ви телефонувалиAppDelegate().sharedInstance()
pxpgraphics

1
Мені подобається це рішення краще, ніж прийняте (що є "швидким" багатослівним, якщо вам доведеться ним користуватися в усьому світі). Я думав про те, щоб поекспериментувати з « extensionдо», NSApplicationперш ніж я знайшов цю відповідь, але це набагато краще. Сьогодні ви, мабуть, хочете використовувати властивість для обчислень класу, обчислену класом, sharedхоча, можливо, ви хочете опублікувати оновлення для Swift 3?
Патру

1
Насправді я переробляю свій код для використання, static var shared : TournamentDelegate? { get { return NSApplication.shared().delegate as? TournamentDelegate } }який більше відповідає розвиваючому стилю Swift 3 використання обчислюваних властивостей для читання для цього типу речей. Я, мабуть, зможу скинути, як ?тільки буде зроблено рефакторинг, ви не думаєте? (Вибачте, форматування коду в коментарях завжди безлад.)
Патру

@ pxpgraphics UIApplication є однотонним класом, тому не потрібно турбуватися про багаторазові інстанції.
Абхіджіт


6

Спробуйте просто так:

Швидкий 4

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

де у вашому AppDelegate:

// MARK: - Whatever
func whateverWillOccur() {

    // Your code here.

}

5

Ось розширення для UIApplicationDelegateцього дозволяє уникнути жорсткого кодування назви AppDelegateкласу:

extension UIApplicationDelegate {

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

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

на Mac для NSApplicationDelegateцього дає мені: 'Self' is only available in a protocol or as the result of a method in a class; did you mean 'AppDelegate'?. Це застаріло?
пкемб

@pkamb Я щойно спробував це в новому проекті, і у мене немає цієї помилки. Я замінив UIApplicationDelegateна NSApplicationDelegateі UIApplicationна NSApplication.
nyg


4

це дуже просто

Елемент делегата додатка

let app = UIApplication.shared.delegate as! AppDelegate

ви можете викликати метод із синтаксисом одного рядка

app.callingMethod()

Ви можете отримати доступ до змінної за допомогою цього коду

app.yourVariable = "Assigning a value"

2

У моєму випадку я був відсутній import UIKitнад своїм NSManagedObjectпідкласом. Після імпортування я міг усунути цю помилку, як UIApplicationі частинаUIKit

Сподіваюся, це допомагає іншим !!!


2

Я використовую це в Swift 2.3.

1.в клас AppDelegate

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

2.Задзвоніть AppDelegate за допомогою

let appDelegate = AppDelegate.sharedInstance

2
extension AppDelegate {

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

2

Станом на iOS 12.2 та Swift 5.0, AppDelegateце не визнаний символ. UIApplicationDelegateє. Тому будь-які відповіді, на які посилаються AppDelegate, більше не є правильними. Наступна відповідь правильна і дозволяє уникнути розгортання, який деякі розробники вважають запахом коду:

import UIKit

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

1
У swift5 ваш код видасть попередження "UIApplication.delegate повинен використовуватися лише з основного потоку". Чи можете ви оновити відповідь.
Махеш Нарла

що fatalErrorфункціонально еквівалентно силі розкручування!
пкемб

1

У Swift 3.0 ви можете отримати appdelegateпосилання на:

let appDelegate = UIApplication.shared.delegate as! AppDelegate

0

У Xcode 6.2 це також працює

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

let aVariable = appDelegate.someVariable

2
v01d, звідки ти це взяв?
NSPratik
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.