DirTy™의 하루일과/DirTy™의 가당찮은iOS

[IOS] background, foreground 타이머돌리기.

DirTy™ 2015. 1. 12. 14:32

아무생각없이 코딩을 하고있다가 문득 백그라운드에서 포어그라운드로 넘어올때 한참의 시간이 지나도 화면이 갱신되지 않는 현상을 발견했다. 안드로이드에서는 기본적으로 제공되고 있는것 같아 아무생각 없이 지나쳤는데 아이폰 쪽에서는 처리해주는 AppDelegate에 메서드가 구현되어있었다.


- (void)applicationDidEnterBackground:(UIApplication *)application // 백그라운드 진입시 호출

- (void)applicaitonWillEnterForeground:(UIApplication *)application // 포어그라운드 진입시 호출


앱이 백그라운드 상태에서 포어그라운드로 넘어올때 첫화면부터 시작하고싶어 구글링해보니

plist에 Application does not run in background를 YES로 해주면 무조건 재갱신이 된다.


하지만 무조건 적으로 재갱신되는 화면 보다는 백그라운드에서 3분이지나면 첫화면으로 이동하고 싶어서 아래와 같이 구현해 보았다. xcode 6.1 IOS SDK 8.1기준으로 문제없이 돌아간다.


- (void)applicationDidEnterBackground:(UIApplication *)application

{

    //check if application status is in background

    if ( [UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {

        

        //change status after time

        [self runBackgroundTask:180]; // 백그라운드로 상태에서 180초후에 화면갱신을 위해 걸어둠.

    }

}


- (void)applicationWillEnterForeground:(UIApplication *)application

{

     // 백그라운드 상태에서 180 이후에 포어그라운드 상태로 올라왔을 경우 화면 재갱신을 하고 화면 백그라운드 플래그 변경

    if(backGroundApp) {

        NSLog(@"backGroundApp restart");

        [self dostuffstartApp]; // 화면을 재갱신 한다

        [self backGroundToforeGroundApp]; // 화면 재갱신 플래그 변경

    } else {

        NSLog(@"backGroundApp invalidate");

        [restartTimer invalidate]; // NSTimer를 invalidate

    }

}

    

//run background task

-(void)runBackgroundTask:(NSInteger)time {

    //check if application is in background mode

    if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {

        // task를 생성후 비동기로 NSRunLoop 실행

        __block UIBackgroundTaskIdentifier bgTask = [app beginBackgroundTaskWithExpirationHandler:^{

            [app endBackgroundTask:bgTask];

            bgTask = UIBackgroundTaskInvalid;

        }];

        

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

            restartTimer = [NSTimer scheduledTimerWithTimeInterval:time target:self selector:@selector(backGroundToforeGroundApp) userInfo:nil repeats:NO];

            [[NSRunLoop currentRunLoop] addTimer:restartTimer forMode:NSDefaultRunLoopMode];

            [[NSRunLoop currentRunLoop] run];

        });

    }

}


- (void)backGroundToforeGroundApp {

    if(backGroundApp) {

        backGroundApp = FALSE;

    }else {

        backGroundApp = TRUE;

    }

    

    if(USE_DEGUG) {

        NSLog(@"180sec later for background... FLAG = %d", backGroundApp);

    }

}


- (void)dostuffstartApp {

    NSString *storyboardName = @"Main_iPhone";


    _storyBoard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];

    UINavigationController *initViewController = [_storyBoard instantiateInitialViewController];

    [self.window setRootViewController:initViewController];

    

    loginObject.user_id = @"";

    loginObject.user_pass = @"";


    [loginObject readLoginData];

    

    if(loginObject.auto_login) {

        // 자동 로그인시 인트로 화면으로 변경

        IntroViewController *view = [self.storyBoard instantiateViewControllerWithIdentifier:@"IntroViewController"];

        [self.window setRootViewController:view];

    } else {

        [NSThread sleepForTimeInterval:1.0];

    }

}