从AppDelegate调用方法-Objective-C [英] Call a method from AppDelegate - Objective-C

查看:78
本文介绍了从AppDelegate调用方法-Objective-C的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在applicationDidEnterBackground方法内从AppDelegate.m调用我的ViewController.m的现有方法,所以我找到了此链接:

I was trying to call an existing method of my ViewController.m from AppDelegate.m inside the applicationDidEnterBackground method, so I found this link: Calling UIViewController method from app delegate, which told me to implement this code:

在我的ViewController.m

In my ViewController.m

-(void)viewDidLoad
{
    [super viewDidLoad];

    AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    appDelegate.myViewController = self;
}

在我的AppDelegate中:

In my AppDelegate:

@class MyViewController;

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (weak, nonatomic) MyViewController *myViewController;

@end

在AppDelegate的实现中:

And in the AppDelegate's implementation:

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    [self.myViewController method];
}

所以我将这段代码放在我的项目中,并且工作正常,但是我不明白代码的工作方式. sharedApplication的作用是什么?为什么我必须设置一个委托,而不是仅仅创建一个ViewController实例,例如:

So I put this code in my project and it worked fine, but I didn't understand how the code works, line by line. What does the sharedApplication do? Why must I set a delegate instead of just creating an instance of ViewController, like:

ViewController * instance = [[ViewController alloc] init];
[instance method];

推荐答案

背景信息(类定义与类实例)

这里的重要概念是类定义和类实例之间的区别.

The important concept here is the difference between a class definition and a class instance.

类定义是该类的源代码.例如,ViewController.m包含myViewController类的定义,而AppDelegate.m包含AppDelegate类的定义.您的问题中提到的另一个类是UIApplication.那是系统定义的类,即您没有该类的源代码.

The class definition is the source code for the class. For example ViewController.m contains the definition for the myViewController class, and AppDelegate.m contains the definition for the AppDelegate class. The other class mentioned in your question is UIApplication. That is a system-defined class, i.e. you don't have the source code for that class.

类实例是堆上的一块内存,并且是指向该内存的指针.通常使用这样的代码行创建类实例

A class instance is a chunk of memory on the heap, and a pointer to that memory. A class instance is typically created with a line of code like this

myClass *foo = [[myClass alloc] init];

请注意,alloc在类的堆上保留空间,然后init设置类的变量/属性的初始值.然后,将指向该实例的指针存储在foo中.

Note that alloc reserves space on the heap for the class, and then init sets the initial values for the variables/properties of the class. A pointer to the instance is then stored in foo.

应用程序启动时,会发生以下一系列事件(大致而言):

When your application starts, the following sequence of events occurs (roughly speaking):

  • 系统创建UIApplication类的实例
  • 指向UIApplication实例的指针存储在 系统变量
  • 系统创建AppDelegate类的实例
  • 指向AppDelegate的指针存储在一个名为 delegate在UIApplication实例中
  • 系统创建MyViewController类的实例
  • 指向MyViewController类的指针存储在某处
  • the system creates an instance of the UIApplication class
  • the pointer to the UIApplication instance is stored somewhere in a system variable
  • the system creates an instance of the AppDelegate class
  • the pointer to the AppDelegate is stored in a variable called delegate in the UIApplication instance
  • the system creates an instance of the MyViewController class
  • the pointer to the MyViewController class is stored somewhere

指向MyViewController的指针的存储使事情变得混乱. AppDelegate类具有一个名为window的UIWindow属性. (您可以在AppDelegate.h中看到它.)如果该应用程序只有一个视图控制器,则指向该视图控制器的指针将存储在window.rootViewController属性中.但是,如果应用程序具有多个视图控制器(在UINavigationController或UITabBarController下),则事情会变得复杂.

The storage of the pointer to MyViewController is where things get messy. The AppDelegate class has a UIWindow property called window. (You can see that in AppDelegate.h.) If the app only has one view controller, then the pointer to that view controller is stored in the window.rootViewController property. But if the app has multiple view controllers (under a UINavigationController or a UITabBarController) then things get complicated.

意大利面条代码解决方案

所以您面临的问题是:当系统调用applicationDidEnterBackground方法时,如何获取指向视图控制器的指针?嗯,从技术上讲,应用程序委托在window属性下的某个位置有一个指向视图控制器的指针,但是没有简单的方法来获取该指针(假设该应用程序具有多个视图控制器).

So the issue that you face is this: when the system calls the applicationDidEnterBackground method, how do you get the pointer to the view controller? Well, technically, the app delegate has a pointer to the view controller somewhere under the window property, but there's no easy way to get that pointer (assuming the app has more than one view controller).

另一个线程建议使用意大利面条式代码解决该问题. (请注意,建议使用意大利面条式代码方法,仅是因为该其他线程中的OP不想正确处理通知.)这是意大利面条式代码的工作原理

The other thread suggested a spaghetti code approach to the problem. (Note that the spaghetti code approach was suggested only because the OP in that other thread didn't want to do things correctly with notifications.) Here's how the spaghetti code works

AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.myViewController = self;

此代码检索指向系统创建的UIApplication实例的指针,然后查询delegate属性以获取指向AppDelegate实例的指针.然后,指向self的指针(即指向MyViewController实例的指针)被存储在AppDelegate的属性中.

This code retrieves the pointer to the UIApplication instance that the system created, and then queries the delegate property to get a pointer to the AppDelegate instance. The pointer to self, which is a pointer to the MyViewController instance, is then stored in a property in the AppDelegate.

当系统调用applicationDidEnterBackground时,可以使用指向MyViewController实例的指针.

The pointer to the MyViewController instance can then be used when the system calls applicationDidEnterBackground.

正确的解决方案

正确的解决方案是使用通知(如kkumpavat的回答)

The correct solution is to use notifications (as in kkumpavat's answer)

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
}

- (void)didEnterBackground
{
    NSLog( @"Entering background now" );
}

-(void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

有了通知,您不必存储指向视图控制器的冗余指针,也不必弄清楚系统将指针存储到视图控制器的位置.通过为UIApplicationDidEnterBackgroundNotification调用addObserver,您将告诉系统直接调用视图控制器的didEnterBackground方法.

With notifications, you aren't storing redundant pointers to your view controllers, and you don't have to figure out where the system has stored the pointer to your view controller. By calling addObserver for the UIApplicationDidEnterBackgroundNotification you're telling the system to call the view controller's didEnterBackground method directly.

这篇关于从AppDelegate调用方法-Objective-C的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆