我正在写一个应用程序,如果用户在打电话时正在看应用程序,我需要改变视图。
我实现了以下方法:
- (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: from applicationWillEnterForeground:,但我似乎无法确定在那一点上哪个是当前视图控制器。
有人知道正确的处理方法吗?我肯定我错过了一个显而易见的解决方案。
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。但你可以找到解决的方法,例如,有UINavigationController的委托方法来找出UIViewController何时在其中被呈现。你可以使用这样的东西来跟踪最新的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
在按下home键,然后将应用程序带回前台后,输出顺序为:
will enter foreground
did become active
如果你最初尝试使用viewWillAppear,那么UIApplication。willEnterForegroundNotification可能是你想要的。
Note
从iOS 9及以后版本开始,你不需要移除观察者。文件说明:
如果您的应用程序的目标是iOS 9.0及以上版本或macOS 10.11及以上版本,您可以使用
不需要在观察器的dealloc方法中取消注册。
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。但你可以找到解决的方法,例如,有UINavigationController的委托方法来找出UIViewController何时在其中被呈现。你可以使用这样的东西来跟踪最新的UIViewController。
更新
如果你在不同的位上使用适当的自动调整大小蒙版来布局UI,有时你甚至不需要处理UI的“手动”布局-它只是处理…