앱이 백그라운드에서 돌아올 때 viewWillAppear가 호출되지 않는 이유는 무엇입니까?
앱을 작성 중이며 전화 통화 중 사용자가 앱을보고있는 경우보기를 변경해야합니다.
다음 방법을 구현했습니다.
- (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 : 메서드에 넣고 모든 가능한 시나리오를 처리하도록하십시오.
applicationWillEnterForeground :에서 viewWillAppear :를 호출하려고 시도했지만 해당 시점의 현재 뷰 컨트롤러를 정확하게 파악할 수 없습니다.
아무도 이것을 처리하는 올바른 방법을 알고 있습니까? 확실한 해결책이 누락되었다고 확신합니다.
이 방법 viewWillAppear
은 다른 응용 프로그램에서 다시 전환 할 때 포 그라운드에 놓이는 응용 프로그램의 컨텍스트가 아니라 자신의 응용 프로그램에서 진행되는 상황에서 취해야합니다.
즉, 누군가 다른 응용 프로그램을 보거나 전화를받는 경우 이전에 백그라운드에 있던 앱으로 다시 전환합니다. 우려되는 한 결코 사라지지 않으며 여전히 볼 수 있으므로 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
방법으로 옵저버를 등록 해제 할 필요가 없습니다 .
viewDidLoad:
ViewController 의 메소드 에서 알림 센터를 사용하여 메소드를 호출하고 메소드에서 수행해야 할 작업을 수행하십시오 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");
}
viewWillAppear:animated:
내 의견으로는 iOS SDK에서 가장 혼란스러운 방법 중 하나 인 응용 프로그램 전환과 같은 상황에서는 결코 호출되지 않습니다. 이 메소드는 뷰 컨트롤러의보기와 응용 프로그램의 창 사이의 관계에 따라서 만 호출됩니다 . 즉, 메시지가 화면이 아닌 응용 프로그램의 창에 나타나는 경우에만 메시지가 뷰 컨트롤러로 전송됩니다.
응용 프로그램이 백그라운드로 전환되면 응용 프로그램 창의 최상위 뷰가 더 이상 사용자에게 표시되지 않습니다. 그러나 응용 프로그램 창의 관점에서는 여전히 최상위 뷰이므로 창에서 사라지지 않았습니다. 오히려 응용 프로그램 창이 사라져서 해당 뷰가 사라졌습니다. 그들은 창 에서 사라져 사라지지 않았다 .
따라서 사용자가 응용 프로그램으로 다시 전환하면 창이 다시 나타나기 때문에 분명히 화면에 나타나는 것처럼 보입니다. 그러나 창문의 관점에서 그들은 전혀 사라지지 않았습니다. 따라서 뷰 컨트롤러는 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");
}
스위프트 4.2 / 5
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground),
name: Notification.Name.UIApplicationWillEnterForeground,
object: nil)
}
@objc func willEnterForeground() {
// do what's needed
}
'IT' 카테고리의 다른 글
엔터티 프레임 워크에서 1 : 1 관계에서 연결의 주요 끝은 무엇을 의미합니까? (0) | 2020.03.29 |
---|---|
Git과 GitHub의 차이점 (0) | 2020.03.28 |
Internet Explorer에서 jQuery Ajax 요청이 캐싱되는 것을 방지하는 방법은 무엇입니까? (0) | 2020.03.28 |
안드로이드에서 사용되는 SQLite 버전? (0) | 2020.03.28 |
모든 테이블에 대한 현재 AUTO_INCREMENT 값을 가져옵니다. (0) | 2020.03.28 |