更改默认设置后,我想在AppDelegate中输入前景时刷新myViewController的数据。我的工作是
AppDelegate.m
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
[window addSubview:[navigationController view]];
NSLog(@"APPLICATION DID FINISH LAUNCHING");
// listen for changes to our preferences when the Settings app does so,
// when we are resumed from the backround, this will give us a chance to update our UI
//
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(defaultsChanged:)
name:NSUserDefaultsDidChangeNotification
object:nil];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
/*
Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
*/
NSLog(@"APPLICATION WILL ENTER BACKGROUND");
[myViewController viewDidLoad];
}
myViewController.m
- (void)viewDidLoad
{
NSLog(@"VIEW DID LOAD IN MY VIEW CONTROLLER");
// watch when the app has finished launching so we can update our preference settings and apply them to the UI
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateSettings:)
name:UIApplicationDidFinishLaunchingNotification object:nil];
}
- (void)updateSettings:(NSNotification *)notif
{
myLabel.text = @"data has just been modified";
}
但是,根本没有任何改变。
答案 0 :(得分:35)
您的代码中有2个问题。首先,启动函数的序列(所谓的执行状态)似乎不清楚,第二,你为函数updateSettings
添加了一个监听器,但你从未在上面的代码中调用它,这就是为什么你的应用程序启动时没有任何改变。
首先让我解释一下启动顺序。当应用程序从关闭的设备加载时,会触发这些状态:
application:didFinishLaunchingWithOptions:
applicationDidBecomeActive:
之后,如果按Home键,则会触发这些状态:
applicationWillResignActive:
applicationDidEnterBackground:
然后,如果再次进入应用程序,将发生以下情况:
applicationWillEnterForeground:
applicationDidBecomeActive:
请注意,加载状态仅在第一次加载时出现一次(但在从主页按下后返回时不会出现)。现在,对于每个视图,函数viewDidLoad
将仅被调用一次,这是第一次调用此视图。如果再次调用此视图(在加载之后),则将调用函数viewWillAppear
。因此,通常在viewWillAppear
函数中进行刷新。
我在代码中注意到的一个重要的不正确之处是使用了主委托函数。在applicationWillEnterForeground
中您手动调用了viewDidLoad
,而您不应该这样做,因为我将自动调用此函数,如上所述。我还看到你正在添加不需要的通知中心。
现在让我们看看代码中的第二个问题。您正在为updateSettings
中的功能viewDidLoad
添加通知中心。那么在事件UIApplicationDidFinishLaunchingNotification
之后加载这个视图就会发生,因此实际上你从未调用函数updateSettings
。此外,由于此功能是您班级的成员,因此您不需要通知中心来调用它。当我们需要从另一个类调用函数时,我们通常使用通知中心。您需要做的就是直接从viewDidLoad
调用此函数,如下所示:
[self updateSettings]
如果您需要在按下主页按钮后进行更新,请从viewWillAppear
。
我希望这个快速的解释可以帮助你。
编辑:回答下面的评论
如果你只有一个视图(没有导航控制器...),它出现后第一次停留在内存中并且不再出现(因此不会调用此功能)。在这里你应该抓住事件UIApplicationDidBecomeActiveNotification
,所以做以下事情:
在viewDidLoad
添加通知:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateSettings) name:UIApplicationDidBecomeActiveNotification object:[UIApplication sharedApplication]];
这将允许每次应用程序唤醒时调用函数updateSettings
。还记得最后删除这个监听器:
[[NSNotificationCenter defaultCenter] removeObserver:self];
答案 1 :(得分:1)
您的代码存在许多问题。
- (void)applicationWillEnterForeground:(UIApplication *)application {
NSLog(@"APPLICATION WILL ENTER BACKGROUND");
...
嗯,不,它会进入FOREGROUND,并且正在离开BACKGROUND。
- (void)viewDidLoad {
...
您应添加[super viewDidLoad];
- (void)applicationWillEnterForeground:(UIApplication *)application {
[myViewController viewDidLoad];
...
嗯,不,不要自己打电话给viewDidLoad
,因为它应该只被系统调用一次。超类或子类可能与多个调用不兼容。
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateSettings:) name:UIApplicationDidFinishLaunchingNotification object:nil];
...
通过多次调用viewDidLoad,您实际上是为同一事件注册了多个观察者。您需要在代码中使用与removeObserver
一样多的addObserver
调用对称(注意您也可以同时删除多个观察者)。
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(defaultsChanged:)
name:NSUserDefaultsDidChangeNotification
object:nil];
好吧,我们没有看到您defaultsChanged:
的实施,因此不清楚您要实现的目标。是否将BOOL设置为YES并随后检查该值以确定首选项是否已更改?那样的东西?
- (void)defaultsChanged:(id)notif {
self.refreshData = YES;
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
if (self.refreshData) {
self.refreshData = NO;
// we refresh data now
...
}
}