luc*_*rci 12 iphone objective-c uiviewcontroller ios appdelegate
我试图ViewController.m
从方法AppDelegate.m
内部 调用my的现有方法applicationDidEnterBackground
,所以我找到了这个链接:从app delegate调用UIViewController方法,它告诉我实现这段代码:
在我的ViewController.m中
-(void)viewDidLoad
{
[super viewDidLoad];
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.myViewController = self;
}
Run Code Online (Sandbox Code Playgroud)
在我的AppDelegate中:
@class MyViewController;
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (weak, nonatomic) MyViewController *myViewController;
@end
Run Code Online (Sandbox Code Playgroud)
在AppDelegate的实现中:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[self.myViewController method];
}
Run Code Online (Sandbox Code Playgroud)
所以我把这个代码放在我的项目中,它工作得很好,但我不明白代码如何工作,一行一行.怎么sharedApplication
办?为什么我必须设置一个委托而不是只创建一个ViewController实例,如:
ViewController * instance = [[ViewController alloc] init];
[instance method];
Run Code Online (Sandbox Code Playgroud)
use*_*109 17
背景信息(类定义与类实例)
这里重要的概念是类定义和类实例之间的区别.
的类定义是类的源代码.例如,ViewController.m
包含myViewController
类的定义,并AppDelegate.m
包含类的定义AppDelegate
.你问题中提到的另一个类是UIApplication
.这是一个系统定义的类,即您没有该类的源代码.
甲类实例是对堆内存块,和一个指针存储器.通常使用这样的代码行创建类实例
myClass *foo = [[myClass alloc] init];
Run Code Online (Sandbox Code Playgroud)
请注意,alloc
为类保留堆的空间,然后init
设置类的变量/属性的初始值.然后存储指向该实例的指针foo
.
当您的应用程序启动时,会发生以下事件序列(粗略地说):
delegate
UIApplication实例中调用的变量
中存储指向MyViewController的指针是事情变得混乱的地方.AppDelegate类具有一个名为的UIWindow属性window
.(您可以在AppDelegate.h中看到.)如果应用程序只有一个视图控制器,那么指向该视图控制器的指针将存储在该window.rootViewController
属性中.但是如果应用程序有多个视图控制器(在UINavigationController或UITabBarController下),那么事情会变得复杂.
意大利面条代码解决方案
所以你面临的问题是:当系统调用applicationDidEnterBackground
方法时,你如何获得指向视图控制器的指针?好吧,从技术上讲,app委托在window
属性下的某个地方有一个指向视图控制器的指针,但是没有简单的方法来获取指针(假设应用程序有多个视图控制器).
另一个线程建议使用意大利面条代码来解决问题.(请注意,建议使用意大利面条代码方法只是因为其他线程中的OP不希望正确处理通知.)以下是意大利面条代码的工作原理
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.myViewController = self;
Run Code Online (Sandbox Code Playgroud)
此代码检索指向系统创建的UIApplication实例的指针,然后查询该delegate
属性以获取指向AppDelegate实例的指针.指向self
MyViewController实例的指针然后存储在AppDelegate的属性中.
然后可以在系统调用时使用指向MyViewController实例的指针 applicationDidEnterBackground
.
正确的解决方案
正确的解决方案是使用通知(如kkumpavat的答案)
- (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];
}
Run Code Online (Sandbox Code Playgroud)
通过通知,您不会将冗余指针存储到视图控制器,也不必确定系统将指针存储到视图控制器的位置.通过调用addObserver
了UIApplicationDidEnterBackgroundNotification
你告诉系统调用视图控制器的didEnterBackground
直接方法.
你有两个问题.
1)sharedApplication
做什么?
该[UIApplication sharedApplication]
给你UIApplication的实例属于您的应用程序.这是您App的集中控制点.有关更多信息,您可以在iOS开发人员站点上阅读UIApplication类参考.
2)为什么我必须设置委托而不是仅创建ViewController的实例?使用/ 再次
创建控制器将创建新实例,并且此新实例不指向您所指的控制器.所以你不会得到你想要的结果.
但是在这个特定的用例中,你不需要参考你的控制器.ViewController可以在函数中注册通知并在函数中取消注册.AppDelegate
alloc
init
applicationDidEnterBackground
AppDelegate
UIApplicationDidEnterBackgroundNotification
viewDidLoad
dealloc
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(yourMethod) name:UIApplicationDidEnterBackgroundNotification object:nil];
//Your implementation
}
-(void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
14126 次 |
最近记录: |