ios 进入前台后刷新数据

jjhzyzn0  于 2022-12-01  发布在  iOS
关注(0)|答案(3)|浏览(136)

更改默认设置后,我想在AppDelegate中进入前台时刷新myViewController的数据。
应用委托. 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];
}

myView控制器. 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";
}

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

e5nqia27

e5nqia271#

您的代码中有两个问题。首先,启动函数的顺序(所谓的执行状态)对您来说似乎不清楚,其次,您为函数updateSettings添加了一个侦听器,但在上面的代码中从未调用过它,这就是为什么应用启动时没有任何变化。
首先让我来解释一下启动顺序。当一个应用程序从一个关闭的设备加载时,会触发这些状态:

application:didFinishLaunchingWithOptions:
applicationDidBecomeActive:

之后,如果您按下主屏幕按钮,则会触发以下状态:

applicationWillResignActive:
applicationDidEnterBackground:

然后,如果您再次进入应用程序,将发生以下情况:

applicationWillEnterForeground:
applicationDidBecomeActive:

请注意,加载状态只在第一次加载时出现一次(而不是在您从Home键返回后)。现在,对于每个视图,函数viewDidLoad将只被调用一次,这是该视图第一次被调用。如果再次调用该视图(在加载后),则函数viewWillAppear将被调用。因此,通常刷新发生在viewWillAppear函数中。
我在你的代码中注意到一个重要的不恰当的地方,那就是主代理函数的使用。在applicationWillEnterForeground中,你手动调用了viewDidLoad,而你不应该这样做,因为这个函数会被自动调用,正如我上面解释的那样。我还看到你添加了不需要的通知中心。
现在让我们看看代码中的第二个问题。您在viewDidLoad中为函数updateSettings添加了一个通知中心。这个视图的加载将在UIApplicationDidFinishLaunchingNotification事件之后发生,因此在实践中您从未调用过函数updateSettings。此外,由于此函数是您的类的成员,您不需要通知中心来调用它。当我们需要调用另一个类中的函数时,我们通常会使用通知中心。您只需直接从viewDidLoad调用此函数,如下所示:

[self updateSettings]

如果你需要在按下home键后更新,请从viewWillAppear调用该函数。
我希望这个快速的解释对你有所帮助。

编辑:回答您在下面的意见

如果你只有一个视图(没有导航控制器...),在它第一次出现后,它将停留在内存中,不会再出现(因此不调用此函数)。这里你应该捕捉事件UIApplicationDidBecomeActiveNotification,所以执行以下操作:
viewDidLoad中添加通知:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateSettings) name:UIApplicationDidBecomeActiveNotification object:[UIApplication sharedApplication]];

这将允许在每次应用唤醒时调用函数updateSettings。另外,请记住在最后删除此侦听器,方法是:

[[NSNotificationCenter defaultCenter] removeObserver:self];
b0zn9rqh

b0zn9rqh2#

您的程式码有许多问题。

混淆前景和背景

- (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
        ...
    }
}
qojgxg4l

qojgxg4l3#

Swift 5版本可跟踪应用程序何时激活

// subscribe to notification once
override func viewDidLoad() {
    super.viewDidLoad()
    subscribeToNotification()
}

// Actual subscription
private func subscribeToNotification() {
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(didBecomeActive),
        name: UIApplication.didBecomeActiveNotification,
        object: nil
    )
}

// Where's where the refreshing logic goes
@objc private func didBecomeActive() {
    print("Do the refreshing")
}

另一种方法是订阅willEnterForegroundNotification通知。

private func subscribeToNotifications() {
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(didBecomeActive),
        name: UIApplication.willEnterForegroundNotification,
        object: nil
    )
}

相关问题