如何在Swift中获得对应用程序委托的引用?


409

如何在Swift中获得对应用程序委托的引用?

最终,我想使用引用来访问托管对象上下文。


8
请注意,有些人会认为将应用程序委托用作托管对象上下文或其他“全局”对象的容器是一种反模式。考虑让应用程序委托将MOC传递给控制器​​,而不是让控制器找到它。
克里斯托弗·约翰逊

1
@KristopherJohnson Hey Kris,我如何才能方便AppDelegate将依赖项注入视图控制器?以编程方式实例化视图控制器,并使用反射来递归地确定要实例化/注入的对象。有没有什么框架可以帮助您呢?如果我必须手动为每个视图控制器执行此操作,则我的AppDelegate将会非常庞大​​!哦,最好不要为所有事物创建工厂:)
Jimbo,

1
粗略搜索发现Swinject也具有自动装配功能:)
Jimbo,

6
对于谁建议不要放置任何东西,“外来的”,在应用程序委托程序员来说,这是一个有点废话,因为苹果文件明确规定,一"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

Answers:


757

另一个解决方案是正确的,因为它将为您提供对应用程序委托的引用,但这将不允许您访问UIApplication的子类添加的任何方法或变量,例如托管对象上下文。要解决此问题,只需向下转换为“ AppDelegate”或您的UIApplication子类碰巧被调用的任何东西。在Swift 3、4和5中,操作如下:

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

10
万一仍然有人遇到问题,以OS X为目标需要您导入Cocoa才能用于NSApplication.sharedApplication()。我猜想iOS需要同样的功能。
smaurice 2014年

2
这是两个答案中比较有用的。
2014年

3
@zacjordaan使用该方法,您将获得该属性的自动补全功能,但实际上无法使用。这样,每次使用时都会创建一个AppDelegate类的新实例。您最好使用可通过sharedApplication单例访问的委托。至于第二个问题,是的,您可能想使用一个常数。即使您可能正在更改AppDelegate的属性,也可能不会将指针重新分配给其他任何对象,在这种情况下,不需要变量。不过,这完全取决于您。做适合您需求的事情。
Mick MacCallum 2014年

2
极好的建议!我错误地认为AppDelegate()是单例的,但是在考虑了您所说的内容之后,我意识到,如果是那样的话,将没有供我们以这种方式使用的sharedApplication模式。当然,如果不需要,我不想生成不必要的实例,因此您的常量声明将非常适合;谢谢。
zacjordaan 2014年

4
我不想将其添加为单独的答案,但要使用自己的方法获取AppDelegate,请在项目中同时使用Swift和Obj-c的属性。应在#ProjectName-BridgingHeader中添加#import“ AppDelegate.h” .h“
Marcin Mierzejewski,

44

斯威夫特4.2

在Swift中,易于在VC中访问

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

25

便利构造

在代码末尾添加AppDelegate类

迅捷5

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

要在您的课程中使用AppDelegate参考?


调用AppDelegate方法

appDelegate()。setRoot()


很好地解释setRoot()的功能以及何时调用它。例如,可以从ViewController调用它吗?从单元测试中尚未设置窗口的地方?更多的上下文将是很棒的。
Houman

@Houman setRoot是AppDelegate的方法,可以用于在多个Root或ParentViewController之间切换,并且可以是任何方法。讨论是关于如何获取AppDelegate的引用以进行进一步的访问,但希望setRoot也必须清楚。
AiOsN

19

与Objective-C几乎相同

let del = UIApplication.sharedApplication().delegate


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类中为ex创建一个方法

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命名的想法。谢谢!
John Griffiths

2
您的示例在AppDelegate每次调用时仍会实例化一个新对象AppDelegate().sharedInstance()
pxpgraphics,2016年

1
我喜欢这种解决方案,而不是接受的解决方案(如果您必须全部使用它,这是“笨拙”的冗长)。在找到此答案之前,我曾想过尝试使用extensionfor NSApplication,但这要好得多。如今,您可能想使用类计算的只读属性shared,也许您想发布Swift 3的更新?
Patru

1
实际上,我正在重构我的代码以使其使用static var shared : TournamentDelegate? { get { return NSApplication.shared().delegate as? TournamentDelegate } },这与正在开发的Swift 3样式(针对此类事物使用计算的只读属性)更加吻合。?重构完成后,我大概就能删除了,不是吗?(对不起,注释中的代码格式总是一团糟。)
Patru

@ pxpgraphics UIApplication是一个单例类,因此无需担心多个实例化。
阿比吉斯(Abhijith)'17


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

@pkamb我刚刚在一个新项目中尝试过,但没有这个错误。我换过UIApplicationDelegate通过NSApplicationDelegateUIApplication通过NSApplication
nyg,


4

这很简单

应用程序委托实例

let app = UIApplication.shared.delegate as! AppDelegate

您可以使用一种语法来调用方法

app.callingMethod()

您可以使用此代码访问变量

app.yourVariable = "Assigning a value"

2

就我而言,我不在子类的import UIKit顶部NSManagedObject。导入后,我可以删除该错误,因为它UIApplicationUIKit

希望对别人有帮助!


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必须仅从主线程使用”警告。你能更新答案吗?
Mahesh Narla

fatalError是功能上等同于力展开!
pkamb

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.