IT

앱이 백그라운드에서 돌아올 때 viewWillAppear가 호출되지 않는 이유는 무엇입니까?

lottoking 2020. 3. 28. 10:46
반응형

앱이 백그라운드에서 돌아올 때 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
}

참고 URL : https://stackoverflow.com/questions/5277940/why-does-viewwillappapp-not-get-called-when-an-app-comes-back-from-the-backgroun

반응형