iOS 7 멀티 태스킹 스위처에서 스크린 샷 제어


98

iOS 7의 새로운 멀티 태스킹 스위처, 특히 앱이 최대 절전 모드로 전환 될 때 OS가 캡처하는 스크린 샷에 대한 정보를 찾으려고 노력하고 있습니다.

여기에 이미지 설명 입력

이 기능이나 스크린 샷을 완전히 끌 수있는 방법이 있습니까? 아니면 스위처에서 앱을 모두 숨길 수 있습니까? 앱은 백그라운드에서 실행되어야하지만 앱의 스크린 샷을 표시하고 싶지 않습니다.

스크린 샷은 잠재적으로 보안 위험이 있으므로 기기의 홈 버튼을 두 번 클릭하는 모든 사람이 카드 번호 또는 계정 요약을 사용할 수있는 뱅킹 앱 라인을 고려하십시오.

이것에 대한 통찰력이있는 사람이 있습니까? 감사.


1
내 현재 솔루션은 앱이 최대 절전 모드에 들어가면 앱 로고가있는 빈보기를로드하고 앱이 반환 될 때 제거하는 것이지만 해당 솔루션은 관리하기 어렵고 우아한 솔루션이 아닌 해킹처럼 보입니다. 또한이 솔루션은 장치 등에 따라 때때로 실패합니다. 따라서 실제로 사용할 수있는 솔루션이 아닙니다.
Tommie 2013-09-23

답변:


101

에서 백그라운드에서 실행 귀하의 UI를 준비 , 애플은 말한다 :

앱 스냅 샷을위한 UI 준비

앱이 백그라운드로 들어가고 델리게이트 메서드가 반환 된 후 UIKit은 앱의 현재 사용자 인터페이스에 대한 스냅 샷을 생성합니다. 시스템은 앱 전환기에 결과 이미지를 표시합니다. 또한 앱을 포 그라운드로 되돌릴 때 일시적으로 이미지를 표시합니다.

앱의 UI에는 비밀번호 나 신용 카드 번호와 같은 민감한 사용자 정보가 포함되어서는 안됩니다. 인터페이스에 이러한 정보가 포함되어 있으면 백그라운드로 들어갈 때보기에서 제거하십시오. 또한 앱의 콘텐츠를 가리는 경고, 임시 인터페이스 및 시스템보기 컨트롤러를 닫습니다. 스냅 샷은 앱의 인터페이스를 나타내며 사용자가 인식 할 수 있어야합니다. 앱이 포 그라운드로 돌아 오면 데이터와 뷰를 적절하게 복원 할 수 있습니다.

기술 Q & A QA1838 : 작업 전환기에 민감한 정보가 나타나지 않도록 방지를 참조하십시오 .

민감한 정보를 모호하게 / 바꾸는 것 외에도을 통해 화면 스냅 샷을 찍지 않도록 iOS 7에 지시 할 수 있습니다 ignoreSnapshotOnNextApplicationLaunch.

앱이 다시 시작될 때 스냅 샷이 앱의 사용자 인터페이스를 올바르게 반영 할 수 없다고 생각되면을 호출 ignoreSnapshotOnNextApplicationLaunch하여 해당 스냅 샷 이미지가 생성되지 않도록 할 수 있습니다 .

그럼에도 불구하고 화면 스냅 샷이 여전히 촬영 된 것으로 보이므로 버그 보고서를 제출했습니다. 그러나 추가로 테스트하고이 설정을 사용하는 것이 도움이되는지 확인해야합니다.

엔터프라이즈 앱인 경우 구성 프로필 참조allowScreenShot제한 페이로드 섹션에 설명 된 적절한 설정을 살펴볼 수도 있습니다 .


여기 내가 필요한 것을 달성하는 구현이 있습니다. 자신의을 제시 UIImageView하거나 위임 프로토콜 패턴을 사용하여 기밀 정보를 가릴 수 있습니다.

//  SecureDelegate.h

#import <Foundation/Foundation.h>

@protocol SecureDelegate <NSObject>

- (void)hide:(id)object;
- (void)show:(id)object;

@end

그런 다음 내 앱 위임에 해당 속성을 부여했습니다.

@property (weak, nonatomic) id<SecureDelegate> secureDelegate;

내 뷰 컨트롤러가 설정합니다.

- (void)viewDidLoad
{
    [super viewDidLoad];

    AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
    delegate.secureDelegate = self;
}

뷰 컨트롤러는 분명히 해당 프로토콜을 구현합니다.

- (void)hide:(id)object
{
    self.passwordLabel.alpha = 0.0;
}

- (void)show:(id)object
{
    self.passwordLabel.alpha = 1.0;
}

그리고 마지막으로 내 앱 델리게이트는이 프로토콜과 속성을 자체적으로 사용합니다.

- (void)applicationWillResignActive:(UIApplication *)application
{
    [application ignoreSnapshotOnNextApplicationLaunch];  // this doesn't appear to work, whether called here or `didFinishLaunchingWithOptions`, but seems prudent to include it

    [self.secureDelegate hide:@"applicationWillResignActive:"];  // you don't need to pass the "object", but it was useful during my testing...
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    [self.secureDelegate show:@"applicationDidBecomeActive:"];
}

다른 사람들이 지적했듯이 앱이 실행되는 동안 홈 버튼을 두 번 탭할 때 후자가 호출되지 않기 때문에 applicationWillResignActive권장되는 대신 사용 applicationDidEnterBackground하고 있습니다.

위임 프로토콜 패턴이 아닌 알림을 사용하여이 모든 것을 처리 할 수 ​​있기를 원하지만 제한된 테스트에서는 알림이 적시에 충분히 처리되지 않지만 위의 패턴은 정상적으로 작동합니다.


6
여기에서 언급했듯이 stackoverflow.com/questions/18937313/… 동작이 시뮬레이터에서 장치에서와 항상 동일하지는 않습니다!
Michael Forrest

5
무엇의 가치를 들어, ignoreSnapshotOnNextApplicationLaunch이 상태 복원 중에 호출되지 않은 경우 설명 된 방법은 무시됩니다 여기에 .
Charles A.

3
스크린 샷은 applicationDidEnterBackground까지 캡처되지 않으므로 applicationWillResignActive에서 수행 할 필요가 없습니다. 홈 버튼을 두 번 탭하면 스크린 샷이 찍히지 않습니다. 지금보고있는 화면이 라이브입니다. 확인하기 위해 화면에 애니메이션을 추가합니다 (예 : 순환 배경색). 그런 다음 다른 앱을 선택하면 실제 스크린 샷을 찍기 전에 applicationDidEnterBackground가 호출됩니다.
honus

3
BTW, 나는 Apple 엔지니어로부터 문서 ignoreSnapshotOnNextApplicationLaunch가 잘못 되었다는 통보를 받았습니다. 우리 모두가 관찰 한 것처럼 스냅 샷은 실제로 촬영되었지만 다음 출시시에는 사용되지 않을 것입니다.
Rob

2
ignoreSnapshotOnNextApplicationLaunch는 응용 프로그램 시작 중에 스크린 샷이 표시되지 않도록하는 것과 같은 소리를냅니다 . 멀티 태스킹 UI 스크린 샷 또는 애플리케이션이 시작되지 않고 재개되는 경우에는 영향을주지 않습니다.
Glenn Maynard

32

이것은 내 응용 프로그램에 대해 작업 한 솔루션입니다.

Tommy가 말했듯이 : applicationWillResignActive를 사용할 수 있습니다. 내가 한 일은 내 SplashImage로 UIImageView를 만들고 그것을 내 주 창에 하위보기로 추가하는 것이 었습니다.

(void)applicationWillResignActive:(UIApplication *)application
{
    imageView = [[UIImageView alloc]initWithFrame:[self.window frame]];
    [imageView setImage:[UIImage imageNamed:@"Portrait(768x1024).png"]];
    [self.window addSubview:imageView];
}

홈 버튼을 두 번 탭하면 applicationDidEnterBackground가 트리거되지 않고 applicationWillResignActive가 실행되므로 applicationDidEnterBackground 대신이 메서드를 사용했습니다. 나는 사람들이 다른 경우에도 유발 될 수 있다고 말하는 것을 들었 기 때문에 문제가 있는지 확인하기 위해 여전히 테스트 중이지만 아직까지는 없습니다! ;)

여기에 imageview를 제거하려면 :

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    if(imageView != nil) {
        [imageView removeFromSuperview];
        imageView = nil;
    }
}

도움이 되었기를 바랍니다!

사이드 노트 : 시뮬레이터와 실제 장치 모두에서 테스트했습니다. 시뮬레이터에는 표시되지 않지만 실제 장치에서는 작동합니다!


2
한 가지 단점이 있습니다. 특히 사용자가 알림 도크를 내리면 applicationWillResignActive가 호출됩니다. 따라서 손가락을 위에서 아래로 슬라이드하면 해당 이미지가 표시되지만 앱 콘텐츠가 표시 될 것으로 예상됩니다.
Kirill Gamazkov 2014

4
applicationWillResignActive에서 민감한 정보를 흐리게 처리하고 aplicationDidEnterBackground에 imageView를 설정하는 것이 좋습니다
Kirill Gamazkov 2014

이것은 작동하지만 xCode6으로 빌드 된 iOS7에 배포 할 때 회전 버그가 있습니다. stackoverflow.com/questions/26147068/…
Alex Stone

applicationWillResignActive 에서 언급 한 코드를 작성하면 내 앱을 전경 상태로 되돌릴 때 무엇을 볼 수 있습니까? "Portrait (768x1024) .png"이미지 또는 실제 화면이 표시됩니까?
NSPratik

2
@Pratik : applicationDidBecomeActive 메서드에서 다시 제거하지 않는 한 이미지가 표시됩니다 (위 참조).
Laura

14

이 빠르고 쉬운 방법은 iOS7 이상의 앱 전환기에서 앱 아이콘 위에 검은 색 스냅 샷을 생성합니다.

먼저 앱의 키 창 (일반적으로 application : didFinishLaunchingWithOptions의 AppDelegate.m에 설정 됨)을 가져 와서 앱이 백그라운드로 이동하려고 할 때 숨 깁니다.

- (void)applicationWillResignActive:(UIApplication *)application
{
    if(isIOS7Or8)
    {
        self.window.hidden = YES;
    }
}

그런 다음 앱이 다시 활성화되면 앱의 키 창 숨기기를 해제합니다.

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    if(isIOS7Or8)
    {
        self.window.hidden = NO;
    }
}

이 시점에서 앱 전환기를 확인하고 앱 아이콘 위에 검은 색 스냅 샷이 표시되는지 확인합니다. 앱을 백그라운드로 이동 한 직후에 앱 전환기를 실행하면 앱의 스냅 샷 (숨기고 싶은 앱)이 표시 될 때까지 5 초 정도 지연 될 수 있습니다. 올 블랙 스냅 샷으로 전환됩니다. 지연이 어떻게되는지 잘 모르겠습니다. 누군가 제안 사항이 있으면 차임하십시오.

스위처에서 검은 색 이외의 색상을 원하는 경우 원하는 배경색으로 하위보기를 추가하여 다음과 같이 할 수 있습니다.

- (void)applicationWillResignActive:(UIApplication *)application
{
    if(isIOS7Or8)
    {
        UIView *colorView = [[[UIView alloc] initWithFrame:self.window.frame] autorelease];
        colorView.tag = 9999;
        colorView.backgroundColor = [UIColor purpleColor];
        [self.window addSubview:colorView];
        [self.window bringSubviewToFront:colorView];
    }
}

그런 다음 앱이 다시 활성화되면이 색상 하위보기를 제거합니다.

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    if(isIOS7Or8)
    {
        UIView *colorView = [self.window viewWithTag:9999];
        [colorView removeFromSuperview];
    }
}

4

다음 솔루션을 사용했습니다. 애플리케이션이 사임 할 때 appWindow 스냅 샷을 View로 가져와 흐림을 추가합니다. 그런 다음이 뷰를 앱 창에 추가합니다.

방법 :

  1. 구현 직전에 appDelegate에서 줄을 추가하십시오.

    static const int kNVSBlurViewTag = 198490;//or wherever number you like
  2. 이 방법을 추가하십시오.

    - (void)nvs_blurPresentedView
        {
            if ([self.window viewWithTag:kNVSBlurViewTag]){
                return;
            }
            [self.window addSubview:[self p_blurView]];
        }
    
        - (void)nvs_unblurPresentedView
        {
            [[self.window viewWithTag:kNVSBlurViewTag] removeFromSuperview];
        }
    
        #pragma mark - Private
    
        - (UIView *)p_blurView
        {
            UIView *snapshot = [self.window snapshotViewAfterScreenUpdates:NO];
    
            UIView *blurView = nil;
            if ([UIVisualEffectView class]){
                UIVisualEffectView *aView = [[UIVisualEffectView alloc]initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]];
                blurView        = aView;
                blurView.frame  = snapshot.bounds;
                [snapshot addSubview:aView];
            }
            else {
                UIToolbar *toolBar  = [[UIToolbar alloc] initWithFrame:snapshot.bounds];
                toolBar.barStyle    = UIBarStyleBlackTranslucent;
                [snapshot addSubview:toolBar];
            }
            snapshot.tag = kNVSBlurViewTag;
            return snapshot;
        }
    
  3. appDelegate 구현을 다음과 같이 만드십시오.

    - (void)applicationWillResignActive:(UIApplication *)application {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
        //...
        //your code
        //...
    
        [self nvs_blurPresentedView];
    }
    
        - (void)applicationWillEnterForeground:(UIApplication *)application {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
        //...
        //your code
        //...
    
        [self nvs_unblurPresentedView];
    }
    

SwiftObjective C로 예제 프로젝트를 만들었습니다 . 두 프로젝트 모두에서 다음 작업을 수행합니다.

-application : didResignActive- 스냅 샷이 생성되고, 흐리게 처리되고, 앱 창에 추가됩니다.

-application : willBecomeActive 블러 뷰가 창에서 제거됩니다.

사용하는 방법:

Objecitve C

  1. AppDelegate+NVSBlurAppScreen프로젝트에 .h 및 .m 파일 추가

  2. -applicationWillResignActive : 메소드에 다음 행을 추가하십시오.

    [self nvs_blurPresentedView];
  3. -applicationDidEnterBackground : 메소드에 다음 행을 추가하십시오.

    [self nvs_unblurPresentedView];

빠른

  1. 프로젝트에 AppDelegateExtention.swift 파일 추가

  2. applicationWillResignActive 함수에서 다음 줄을 추가하십시오.

    blurPresentedView()
  3. applicationDidBecomeActive 함수에 다음 줄을 추가하십시오.

    unblurPresentedView()

2

함수 에서만 사용 [self.window addSubview:imageView];하는 applicationWillResignActive경우이 imageView는 UIAlertView, UIActionSheet 또는 MFMailComposeViewController를 포함하지 않습니다.

최고의 솔루션은

- (void)applicationWillResignActive:(UIApplication *)application
{
    UIWindow *mainWindow = [[[UIApplication sharedApplication] windows] lastObject];
    [mainWindow addSubview:imageView];
}

웹뷰에서 전체 화면 모드로 비디오를 재생하는 경우 매우 좋은 솔루션입니다!
토미

우수한!. 멀티 태스킹 스위처에 들어가기 전에 키패드가 열려 있어도 작동합니다! 감사합니다
Prabhu.Somasundaram 07-07-17

0

이 솔루션은 매우 신뢰할 수 없지만 "답변"으로 내 솔루션을 제공합니다. 가끔 스크린 샷으로 검은 색 화면이 나타나기도하고, 때로는 XIB가 나타나기도하고 앱 자체에서 스크린 샷이 나올 수도 있습니다. 장치 및 / 또는 시뮬레이터에서 실행 여부에 따라 다릅니다.

이 솔루션에는 많은 앱 관련 세부 정보가 포함되어 있으므로 코드를 제공 할 수 없습니다. 그러나 이것은 내 솔루션의 기본 요지를 설명해야합니다.

applicationWillResignActive 아래의 AppDelegate.m에서 iOS7을 실행 중인지 확인하고, 중간에 app-logo가있는 비어있는 새보기를로드합니다. applicationDidBecomeActive가 호출되면 이전 뷰를 다시 시작하여 재설정됩니다.하지만 개발중인 응용 프로그램 유형에 대해 작동합니다.


1
카메라 앱이 수행하는 작업을 확인하면 배경으로 이동할 때 이미지가 흐릿한 이미지로 전환됩니다 (아이콘으로
축소됨에

@Petesh 예, 그것은 좋은 구현입니다. 그러나 질문은 그들이 어떻게 하는가입니다. 개인 API가 두렵습니다.
Rob

@Tommie "장치에 따라 및 / 또는 시뮬레이터에서 실행하는 경우"라고 말합니다. 나를 위해, 나타납니다 시뮬레이터 (나는 철저한 테스트를 완료하지 않은 있지만)가 아니라 장치에서 작동합니다. 장치에서 작동하지 않는다는 것을 알고 있습니까?
Rob

0

활성기를 사용하여 홈 버튼의 더블 클릭을 구성하여 멀티 태스킹을 시작하고 홈 버튼의 기본 더블 클릭 및 멀티 태스킹 창 시작을 비활성화 할 수 있습니다. 이 방법은 스크린 샷을 애플리케이션의 기본 이미지로 변경하는 데 사용할 수 있습니다. 이는 기본 암호 보호 기능이있는 앱에 적용됩니다.


-2

Xamarin.iOS

https://stackoverflow.com/a/20040270/7561 에서 수정 됨

색상 만 표시하는 대신 시작 화면을 표시하고 싶었습니다.

 public override void DidEnterBackground(UIApplication application)
 {
    //to add the background image in place of 'active' image
    var backgroundImage = new UIImageView();
    backgroundImage.Tag = 1234;
    backgroundImage.Image = UIImage.FromBundle("Background");
    backgroundImage.Frame = this.window.Frame;
    this.window.AddSubview(backgroundImage);
    this.window.BringSubviewToFront(backgroundImage);
}

public override void WillEnterForeground(UIApplication application)
{
    //remove 'background' image
    var backgroundView = this.window.ViewWithTag(1234);
    if(null != backgroundView)
        backgroundView.RemoveFromSuperview();
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.