私はアプリを書いていますが、ユーザーが電話で話しているときにアプリを見ている場合は、ビューを変更する必要があります。
次のメソッドを実装しました。
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(@"viewWillAppear:");
_sv.frame = CGRectMake(0.0, 0.0, 320.0, self.view.bounds.size.height);
}
ただし、アプリがフォアグラウンドに戻ったときに呼び出されることはありません。
私は実装できることを知っています:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarFrameChanged:) name:UIApplicationDidChangeStatusBarFrameNotification object:nil];
しかし、私はこれをしたくありません。むしろ、すべてのレイアウト情報をviewWillAppear:メソッドに入れて、考えられるすべてのシナリオを処理できるようにします。
ViewWillAppear:をapplicationWillEnterForeground:から呼び出そうとしましたが、その時点で現在のView Controllerを特定することはできません。
誰もこれに対処する適切な方法を知っていますか?明らかな解決策が欠けていると確信しています。
メソッドviewWillAppear
は、別のアプリから切り替えたときにフォアグラウンドに置かれているアプリケーションのコンテキストではなく、独自のアプリケーションで行われていることのコンテキストで取得する必要があります。
言い換えれば、誰かが別のアプリケーションを見たり、電話をかけたり、バックグラウンドで以前にあったアプリ、つまりアプリを離れたときにすでに表示されていたUIViewControllerに切り替えると、いわば「気にしない」懸念される限り、消えることはなく、表示されたままです。したがって、viewWillAppear
は呼び出されません。
viewWillAppear
を自分で呼び出すことはお勧めしません-破壊すべきではない特定の意味があります!同じ効果を得るためにできるリファクタリングは次のとおりです。
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self doMyLayoutStuff:self];
}
- (void)doMyLayoutStuff:(id)sender {
// stuff
}
次に、適切な通知からdoMyLayoutStuff
をトリガーします。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doMyLayoutStuff:) name:UIApplicationDidChangeStatusBarFrameNotification object:self];
どちらが「現在の」UIViewControllerであるかをすぐに確認できる方法はありません。しかし、あなたはそれを回避する方法を見つけることができます、例えばUIViewControllerがいつ表示されるかを調べるためのUINavigationControllerのデリゲートメソッドがあります。このようなものを使用して、提示された最新のUIViewControllerを追跡できます。
更新
さまざまなビットに適切な自動サイズ変更マスクを使用してUIをレイアウトする場合、UIの「手動」レイアウトを処理する必要さえない場合があります。
短い答え
NotificationCenter
ではなくviewWillAppear
オブザーバーを使用します。
override func viewDidLoad() {
super.viewDidLoad()
// set observer for UIApplication.willEnterForegroundNotification
NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
}
// my selector that was defined above
@objc func willEnterForeground() {
// do stuff
}
長答
アプリがバックグラウンドから戻ったときを確認するには、NotificationCenter
ではなくviewWillAppear
オブザーバーを使用します。これは、どのイベントがいつ発生するかを示すサンプルプロジェクトです。 (これは このObjective-Cの答え の適応です。)
import UIKit
class ViewController: UIViewController {
// MARK: - Overrides
override func viewDidLoad() {
super.viewDidLoad()
print("view did load")
// add notification observers
NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
}
override func viewWillAppear(_ animated: Bool) {
print("view will appear")
}
override func viewDidAppear(_ animated: Bool) {
print("view did appear")
}
// MARK: - Notification oberserver methods
@objc func didBecomeActive() {
print("did become active")
}
@objc func willEnterForeground() {
print("will enter foreground")
}
}
アプリを最初に起動したときの出力順序は次のとおりです。
view did load
view will appear
did become active
view did appear
ホームボタンを押してからアプリをフォアグラウンドに戻した後、出力順序は次のとおりです。
will enter foreground
did become active
したがって、最初にviewWillAppear
を使用しようとした場合は、おそらくUIApplication.willEnterForegroundNotification
が必要です。
IOS 9以降では、オブザーバーを削除する必要はありません。 ドキュメント 状態:
アプリがiOS 9.0以降またはmacOS 10.11以降をターゲットにしている場合、
dealloc
メソッドでオブザーバーの登録を解除する必要はありません。
ViewControllerのviewDidLoad:
メソッドで通知センターを使用してメソッドを呼び出し、そこからviewWillAppear:
メソッドで行うべきことを実行します。 viewWillAppear:
を直接呼び出すことは適切なオプションではありません。
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"view did load");
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationIsActive:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationEnteredForeground:)
name:UIApplicationWillEnterForegroundNotification
object:nil];
}
- (void)applicationIsActive:(NSNotification *)notification {
NSLog(@"Application Did Become Active");
}
- (void)applicationEnteredForeground:(NSNotification *)notification {
NSLog(@"Application Entered Foreground");
}
私の意見では、iOS SDKで最も混乱を招くメソッドの1つであるviewWillAppear:animated:
は、このような状況、つまりアプリケーションの切り替えでは決して呼び出されません。そのメソッドは、View Controllerのビューとアプリケーションのウィンドウとの関係に従ってのみ呼び出されます。つまり、メッセージはViewが画面ではなくアプリケーションのウィンドウに表示される場合にのみView Controllerに送信されます。
アプリケーションがバックグラウンドになると、明らかにアプリケーションウィンドウの一番上のビューがユーザーに表示されなくなります。ただし、アプリケーションウィンドウのパースペクティブでは、これらは依然として最上位のビューであるため、ウィンドウから消えませんでした。むしろ、アプリケーションウィンドウが消えたため、これらのビューは消えました。ウィンドウから()消えたため、それらは消えませんでした。
したがって、ユーザーがアプリケーションに戻ると、ウィンドウが再び表示されるため、明らかに画面に表示されるように見えます。しかし、ウィンドウの観点からは、それらはまったく消えていません。したがって、View ControllerはviewWillAppear:animated
メッセージを取得しません。
できるだけ簡単にするために、次のコードを参照してください。
- (void)viewDidLoad
{
[self appWillEnterForeground]; //register For Application Will enterForeground
}
- (id)appWillEnterForeground{ //Application will enter foreground.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(allFunctions)
name:UIApplicationWillEnterForegroundNotification
object:nil];
return self;
}
-(void) allFunctions{ //call any functions that need to be run when application will enter foreground
NSLog(@"calling all functions...application just came back from foreground");
}