백그라운드에서 앱을 열 때 ViewDidAppear가 호출되지 않습니다


175

나는 나의 값이 0 (라벨) 때 내가보기 컨트롤러가 서로 개폐되는 뷰 컨트롤러가 ViewController내가 설정 한 viewDidAppear라벨에 설정 값 (20)을. 그것은 잘 작동하지만 난 내 응용 프로그램을 종료하지 않고 다시 내 응용 프로그램을 열보다하지만 값이 있기 때문에 변경하지 않을 때 viewDidLoad, viewDidAppear그리고 viewWillAppear아무것도 전화를받을. 앱을 열 때 어떻게 전화를 걸 수 있습니까? 내가해야 할 일이 applicationDidBecomeActive있습니까?


애플리케이션이 활성화되면 로컬 알림을 게시하고 뷰 컨트롤러를 옵저버 및 업데이트 값으로 추가 할 수 있습니다.
Adil Soomro

답변:


314

정확한 이벤트 순서에 대해 궁금한 점은 다음과 같이 앱을 계측 한 것입니다. (@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

1
Danh, UIApplicationWillEnterForegroundNotification을 appDidEnterForeground :에 맵핑했습니다. 약간 오도되지 않습니까? "will"과 "did"에 주목하십시오. 의도적인가요?
Lubiluk

@Lubiluk-의도적이지 않습니다. 편집하겠습니다. 잘 잡았습니다.
danh

4
이것은 매우 유용한 답변이었습니다. 여기에 스위프트 버전을 만들었습니다 .
Suragch

배경 모드의 완벽한 데모!
Marcelo dos Santos

홈 버튼을 두 번 탭하고 앱을 닫을 때의 이벤트 순서는 무엇입니까?
Amjad Husseini

134

Objective-C 사용

의 메소드 UIApplicationWillEnterForegroundNotification에를 등록해야 하며 백그라운드에서 앱이 다시 표시 될 때마다 알림에 등록 된 메소드에서 원하는 모든 작업을 수행 할 수 있습니다. 의 viewWillAppear 또는 viewDidAppear는 응용 프로그램이 포 그라운드로 배경에서 돌아 오면 호출되지 않습니다.ViewControllerviewDidLoadViewController

-(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이 통지.

스위프트 사용

관찰자를 추가하려면 다음 코드를 사용할 수 있습니다

 override func viewDidLoad() {
    super.viewDidLoad()

     NotificationCenter.default.addObserver(self, selector: "doYourStuff", name: UIApplication.willEnterForegroundNotification, object: nil)
 }

 func doYourStuff(){
     // your code
 }

관찰자를 제거하려면 swift의 deinit 기능을 사용할 수 있습니다.

deinit {
    NotificationCenter.default.removeObserver(self)
}

4
그렇습니다 :) 때로는 답을 찾기가 어렵습니다 :)
nsgulliver

@nsgulliver 알림 등록을 수동으로 취소해야합니까?-(void) dealloc {[[NSNotificationCenter defaultCenter] removeObserver : self]; }. 앱이 나를 위해 그것을 할 것인가?
ios

43

스위프트 3.0 ++ 버전

viewDidLoad백그라운드 작업에서 열린 알림을 들으려면 알림 센터에 등록 하십시오 .

NotificationCenter.default.addObserver(self, selector:#selector(doSomething), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil)
        

그런 다음이 기능을 추가하고 필요한 조치를 수행하십시오.

func doSomething(){
    //...
}

마지막으로이 기능을 추가하여 뷰 컨트롤러가 파괴 될 때 알림 관찰자를 정리하십시오.

deinit {
    NotificationCenter.default.removeObserver(self)
}

VC +1 내부의 알림을 처리 할 수있는 쉽고 간단한 솔루션
Mo Zaatar

다른 많은 유사 / 중복 SO 질문 에서이 좋은 대답을 놓쳤다는 것을 믿을 수 없습니다.
Hugo Allexis Cardona 2016 년

11

스위프트 4.2. 버전

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)
}

1
참고로 요즘 더 이상 관찰자를 제거 할 필요가 없습니다 ...
Fattie

3

뷰 컨트롤러가 UIApplicationWillEnterForegroundNotification알림에 등록 하고 그에 따라 반응하도록하십시오.


어떻게하면 되나요? applicationDidBecomeActive에서 viewController를 호출했지만. viewController와 겹치지 않습니까?
Zohaib

2
applicationDidBecomeActive에서 viewController를 호출하지 마십시오 (여러 번 호출되기 때문에 잘못되었습니다). viewDidLoad@nsgulliver가 제안한 것처럼 알림을 등록하십시오 . 여러분 viewDidAppear도 호출 doYourStuff원하는 값으로 라벨을 설정할 수 있습니다.
andreagiavatto

3

UIApplicationWillEnterForegroundNotification에 등록하면 해당 알림에 반응하는 둘 이상의 컨트롤러가 생길 수 있으므로 위험합니다. 알림이 수신 될 때 이러한 컨트롤러가 여전히 표시된다는 것을 보증하는 것은 없습니다.

여기 내가하는 일이 있습니다 : 앱의 델리게이트 didBecomeActive 메소드에서 직접 활성 컨트롤러에서 viewDidAppear 호출을 강제합니다.

아래 코드를 추가하십시오 - (void)applicationDidBecomeActive:(UIApplication *)application

UIViewController *activeController = window.rootViewController;
if ([activeController isKindOfClass:[UINavigationController class]]) {
    activeController = [(UINavigationController*)window.rootViewController topViewController];
}
[activeController viewDidAppear:NO];

7
컨트롤러가 dealloc 대신에 viewWillDisappear에서 UIApplicationWillEnterForegroundNotification에 대해 등록을 취소해야합니다. viewDidAppear를 호출하면 명시 적으로 해킹처럼 보이며 시맨틱 (개인적 관점)을 깨뜨리고 (경험에서) 사람들을 혼란스럽게 할 수 있습니다.
joakim

3

AppDelegate applicationWillEnterForeground에서 이것을 추가하십시오.

func applicationWillEnterForeground(_ application: UIApplication) {        
    // makes viewWillAppear run
    self.window?.rootViewController?.beginAppearanceTransition(true, animated: false)
    self.window?.rootViewController?.endAppearanceTransition()
}

2

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 알림을받지 못하게했습니다. 이 줄을 주석 처리하면 정상적으로 작동합니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.