値が0(ラベル)のView Controllerがあり、そのView Controllerを別のViewController
から開くと、viewDidAppear
を設定してラベルの値20を設定します。正常に機能しますが、アプリを閉じてからアプリを再度開くと、viewDidLoad
、viewDidAppear
、およびviewWillAppear
が何も呼び出されないため、値は変わりません。アプリを開いたときに電話をかけるにはどうすればよいですか。 applicationDidBecomeActive
から何かする必要がありますか?
イベントの正確なシーケンスに興味があるため、次のようにアプリをインストルメントしました(@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
Objective-Cを使用
UIApplicationWillEnterForegroundNotification
のViewController
メソッドにviewDidLoad
を登録する必要があります。アプリがバックグラウンドから復帰するたびに、通知用に登録されたメソッドで何でもしたいことができます。 ViewController
のviewWillAppearまたは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];
}
注viewController
をUIApplicationDidBecomeActiveNotification
に登録すると、アプリがアクティブになるたびにメソッドが呼び出されます。この通知に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)
}
viewDidLoad
で、通知センターに登録して、バックグラウンドアクションから開かれたこれをリッスンします
NotificationCenter.default.addObserver(self, selector:#selector(doSomething), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil)
次に、この関数を追加し、必要なアクションを実行します
func doSomething(){
//...
}
最後に、この関数を追加して、View Controllerが破棄されたときに通知オブザーバーをクリーンアップします。
deinit {
NotificationCenter.default.removeObserver(self)
}
UIApplicationWillEnterForegroundNotificationに登録すると、その通知に反応するコントローラーが複数になる可能性があるため、リスクがあると思います。通知を受信したときにこれらのコントローラーが表示されることを保証するものは何もありません。
私がやることは次のとおりです。アプリのデリゲートdidBecomeActiveメソッドからアクティブコントローラーでviewDidAppearを直接呼び出します。
以下のコードを- (void)applicationDidBecomeActive:(UIApplication *)application
に追加します
UIViewController *activeController = window.rootViewController;
if ([activeController isKindOfClass:[UINavigationController class]]) {
activeController = [(UINavigationController*)window.rootViewController topViewController];
}
[activeController viewDidAppear:NO];
アプリがバックグラウンドから戻ったときに通知されるように、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)
}
View ControllerにUIApplicationWillEnterForegroundNotification
通知を登録してもらい、それに応じて対応するだけです。
これをAppDelegate applicationWillEnterForegroundに追加してみてください。
func applicationWillEnterForeground(_ application: UIApplication) {
// makes viewWillAppear run
self.window?.rootViewController?.beginAppearanceTransition(true, animated: false)
self.window?.rootViewController?.endAppearanceTransition()
}
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通知を受信しなくなりました。 これらの行をコメントしたとき、正常に動作しています。