web-dev-qa-db-ja.com

バックグラウンドからアプリを開くときにViewDidAppearが呼び出されない

値が0(ラベル)のView Controllerがあり、そのView Controllerを別のViewControllerから開くと、viewDidAppearを設定してラベルの値20を設定します。正常に機能しますが、アプリを閉じてからアプリを再度開くと、viewDidLoadviewDidAppear、およびviewWillAppearが何も呼び出されないため、値は変わりません。アプリを開いたときに電話をかけるにはどうすればよいですか。 applicationDidBecomeActiveから何かする必要がありますか?

162
Zohaib

イベントの正確なシーケンスに興味があるため、次のようにアプリをインストルメントしました(@Zohaib、以下のNSNotificationCenterコードを使用して質問に答えることができます)。

// AppDelegate.m

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    NSLog(@"app will enter foreground");
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    NSLog(@"app did become active");
}

// ViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"view did load");

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
}

- (void)appDidBecomeActive:(NSNotification *)notification {
    NSLog(@"did become active notification");
}

- (void)appWillEnterForeground:(NSNotification *)notification {
    NSLog(@"will enter foreground notification");
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog(@"view will appear");
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    NSLog(@"view did appear");
}

起動時の出力は次のようになります。

2013-04-07 09:31:06.505 myapp[15459:11303] view did load
2013-04-07 09:31:06.507 myapp[15459:11303] view will appear
2013-04-07 09:31:06.511 myapp[15459:11303] app did become active
2013-04-07 09:31:06.512 myapp[15459:11303] did become active notification
2013-04-07 09:31:06.517 myapp[15459:11303] view did appear

背景を入力してから前景に再入力します。

2013-04-07 09:32:05.923 myapp[15459:11303] app will enter foreground
2013-04-07 09:32:05.924 myapp[15459:11303] will enter foreground notification
2013-04-07 09:32:05.925 myapp[15459:11303] app did become active
2013-04-07 09:32:05.926 myapp[15459:11303] did become active notification
298
danh

Objective-Cを使用

UIApplicationWillEnterForegroundNotificationViewControllerメソッドにviewDidLoadを登録する必要があります。アプリがバックグラウンドから復帰するたびに、通知用に登録されたメソッドで何でもしたいことができます。 ViewControllerviewWillAppearまたはviewDidAppearは、アプリがバックグラウンドからフォアグラウンドに戻ったときに呼び出されません。

-(void)viewDidLoad{

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doYourStuff)

  name:UIApplicationWillEnterForegroundNotification object:nil];
}

-(void)doYourStuff{

   // do whatever you want to do when app comes back from background.
}

登録している通知の登録を忘れずに忘れないでください。

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

viewControllerUIApplicationDidBecomeActiveNotificationに登録すると、アプリがアクティブになるたびにメソッドが呼び出されます。この通知にviewControllerを登録することはお勧めしません。

Swiftを使用

オブザーバーを追加するには、次のコードを使用できます

 override func viewDidLoad() {
    super.viewDidLoad()

     NSNotificationCenter.defaultCenter().addObserver(self, selector:"doYourStuff", name:
     UIApplicationWillEnterForegroundNotification, object: nil)
 }

 func doYourStuff(){
     // your code
 }

オブザーバーを削除するには、Swiftのdeinit関数を使用できます。

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}
126
nsgulliver

Swift 3.0 ++バージョン

viewDidLoadで、通知センターに登録して、バックグラウンドアクションから開かれたこれをリッスンします

NotificationCenter.default.addObserver(self, selector:#selector(doSomething), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil)

次に、この関数を追加し、必要なアクションを実行します

func doSomething(){
    //...
}

最後に、この関数を追加して、View Controllerが破棄されたときに通知オブザーバーをクリーンアップします。

deinit {
    NotificationCenter.default.removeObserver(self)
}
39
Fangming

UIApplicationWillEnterForegroundNotificationに登録すると、その通知に反応するコントローラーが複数になる可能性があるため、リスクがあると思います。通知を受信したときにこれらのコントローラーが表示されることを保証するものは何もありません。

私がやることは次のとおりです。アプリのデリゲートdidBecomeActiveメソッドからアクティブコントローラーでviewDidAppearを直接呼び出します。

以下のコードを- (void)applicationDidBecomeActive:(UIApplication *)applicationに追加します

UIViewController *activeController = window.rootViewController;
if ([activeController isKindOfClass:[UINavigationController class]]) {
    activeController = [(UINavigationController*)window.rootViewController topViewController];
}
[activeController viewDidAppear:NO];
4
Erwan

スウィフト4.2。バージョン

アプリがバックグラウンドから戻ったときに通知されるように、viewDidLoadのNotificationCenterに登録します

NotificationCenter.default.addObserver(self, selector: #selector(doSomething), name: UIApplication.willEnterForegroundNotification, object: nil)

呼び出す必要のあるメソッドを実装します。

@objc private func doSomething() {
    // Do whatever you want, for example update your view.
}

ViewControllerが破棄されたら、オブザーバーを削除できます。これはiOS9およびmacOS 10.11の下でのみ必要です

deinit {
    NotificationCenter.default.removeObserver(self)
}
4
gebirgsbärbel

View ControllerにUIApplicationWillEnterForegroundNotification通知を登録してもらい、それに応じて対応するだけです。

3
andreagiavatto

これをAppDelegate applicationWillEnterForegroundに追加してみてください。

func applicationWillEnterForeground(_ application: UIApplication) {        
    // makes viewWillAppear run
    self.window?.rootViewController?.beginAppearanceTransition(true, animated: false)
    self.window?.rootViewController?.endAppearanceTransition()
}
2
richc

Appleのドキュメントによると:

(void)beginAppearanceTransition:(BOOL)isAppearing animated:(BOOL)animated;

説明:
子コントローラに、外観が変更されようとしていることを伝えます。カスタムコンテナーコントローラーを実装する場合、このメソッドを使用して、そのビューが表示または非表示に近いことを子に通知します。 viewWillAppear:viewWillDisappear:viewDidAppear:、またはviewDidDisappear:を直接呼び出さないでください

(void)endAppearanceTransition;

説明:

外観が変更された子コントローラーに通知します。カスタムコンテナーコントローラーを実装している場合は、このメソッドを使用して、ビューの移行が完了したことを子に伝えます。

サンプルコード:

(void)applicationDidEnterBackground:(UIApplication *)application
{

    [self.window.rootViewController beginAppearanceTransition: NO animated: NO];  // I commented this line

    [self.window.rootViewController endAppearanceTransition]; // I commented this line

}

質問:修正方法

Ans:アプリケーションでこの行を見つけました。この行により、アプリがViewWillAppear通知を受信しなくなりました。 これらの行をコメントしたとき、正常に動作しています

1
Lakshmi