进入前台后刷新数据

时间:2012-01-27 20:26:16

标签: ios iphone

更改默认设置后,我想在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";
}

但是,根本没有任何改变。

2 个答案:

答案 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。

在viewDidLoad

中缺少超级调用
- (void)viewDidLoad {
    ...

您应添加[super viewDidLoad];

直接调用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
        ...
    }
}