iOS에서 프로그래밍 방식으로 스크린 샷을 찍는 방법


답변:


233

망막 디스플레이 검사를 고려할 때 다음 코드 스 니펫을 사용하십시오.

#import <QuartzCore/QuartzCore.h> 

if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
    UIGraphicsBeginImageContextWithOptions(self.window.bounds.size, NO, [UIScreen mainScreen].scale);
} else {
    UIGraphicsBeginImageContext(self.window.bounds.size);
}

[self.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *imageData = UIImagePNGRepresentation(image);
if (imageData) {
    [imageData writeToFile:@"screenshot.png" atomically:YES];
} else {
    NSLog(@"error while taking screenshot");
}

13
OpenGL ES 레이어와 같은 특정 유형의 화면 내용은 캡처하지 않습니다. Hua-Ying이 가리키는 UIGetScreenImage ().
Brad Larson

12
친애하는 분들, 잊지 마세요 #import <QuartzCore / QuartzCore.h>
Enrico Susatyo

앱에서 방금 찍은 사진을보고있는 경우 스크린 샷이 찍히나요?
John Riselvato

5
이 이미지는 어디에 저장됩니까?
Burhanuddin Sunelwala

3
@ wladimir-palant : Key-Board는 어떻습니까? 사용자 유형의 sceen을 스크린 샷으로 찍을 때 키보드가 캡처되지 않기 때문에 어떻게 화면 캡처에 키보드를 추가 할 수 있습니까?
g212gs

46

아래 방법은 OPENGL 객체에서도 작동합니다.

//iOS7 or above
- (UIImage *) screenshot {

    CGSize size = CGSizeMake(your_width, your_height);

    UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);

    CGRect rec = CGRectMake(0, 0, your_width, your_height);
    [_viewController.view drawViewHierarchyInRect:rec afterScreenUpdates:YES];

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

5
UIGetScreenImage은 개인 API입니다
jonahb

고마워요! 당신은 분명히 내 투표를 얻습니다. 다른 여러 가지 방법을 시도한 후 drawViewHierarchy가 javafx ui를 사용하여 robovm에서 화면을 잡을 수있는 유일한 방법 인 것으로 보입니다.
Christo Smal

이것은 매번 작동하는 것입니다 !!!! 나는 scrreen에 많은 3d 변환을 가지고 있으며 다른 솔루션은 스크린 샷을 망쳤습니다. 이것은 정상적으로 작동합니다. 고마워요!
AndrewK

1
뷰 컨트롤러 탐색 컨트롤러 인 경우 탐색 줄은 포착되지 않는다
라두 Simionescu


20
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, self.view.opaque, 0.0);
[self.myView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

NSData *imageData = UIImageJPEGRepresentation(image, 1.0 ); //you can use PNG too
[imageData writeToFile:@"image1.jpeg" atomically:YES];

1
+1 PNG 사용에 대한 참고 사항. 무손실이며 품질 = 1.0 인 jpeg보다 작습니다.
Rob

1
iOS 7에서는 NavigationBar를 사용하지 않고 대신 빈 공간을 남겨 둡니다.
Ali Sufyan

14
- (UIImage*) getGLScreenshot {
    NSInteger myDataLength = 320 * 480 * 4;

    // allocate array and read pixels into it.
    GLubyte *buffer = (GLubyte *) malloc(myDataLength);
    glReadPixels(0, 0, 320, 480, GL_RGBA, GL_UNSIGNED_BYTE, buffer);

    // gl renders "upside down" so swap top to bottom into new array.
    // there's gotta be a better way, but this works.
    GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
    for(int y = 0; y <480; y++)
    {
        for(int x = 0; x <320 * 4; x++)
        {
            buffer2[(479 - y) * 320 * 4 + x] = buffer[y * 4 * 320 + x];
        }
    }

    // make data provider with data.
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL);

    // prep the ingredients
    int bitsPerComponent = 8;
    int bitsPerPixel = 32;
    int bytesPerRow = 4 * 320;
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

    // make the cgimage
    CGImageRef imageRef = CGImageCreate(320, 480, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

    // then make the uiimage from that
    UIImage *myImage = [UIImage imageWithCGImage:imageRef];
    return myImage;
}

- (void)saveGLScreenshotToPhotosAlbum {
    UIImageWriteToSavedPhotosAlbum([self getGLScreenshot], nil, nil, nil);  
}

소스 .


1
myDataLength에 320 * 480의 4를 곱한 이유는 무엇입니까?
Jab

2
이것은 또한 그들이 우리에게 더 쉬운 방법을 제공하지 않는다는 것을 매우 바보처럼 보입니다.
Jab

320 * 480은 픽셀 수입니다. 시간은 4이므로 각 픽셀에 대해 RGBA가 있습니다.
Aistina

아이폰 4에서 실행할 때 스케일 팩터로 배수를 기억하십시오 :-)
MrDatabase

1
@Aistina 사용 UIImage *myImage = [[UIImage alloc] initWithCGImage:imageRef scale:1.0 orientation:UIImageOrientationDownMirrored];하고 더 이상 'buffer2'가 필요하지 않습니다. BTW 그것은 당신이 메모리 관리, free () 또는 release () 호출에 대해 잊어 버린 것처럼 보입니다 ...
Oleg Trakhman

10

신속하게

func captureScreen() -> UIImage
{

    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, false, 0);

    self.view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)

    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()

    UIGraphicsEndImageContext()

    return image
}

9

지금은 UIGetScreenImage ()를 사용할 수있는 것처럼 보이는 게시물을 참조하십시오 .


9
이것은 iOS 4에서 다시 허용되지 않습니다.
sudo rm -rf

9

iOS10부터는 조금 더 단순 해집니다. UIKit은 다음과 같은 기능 UIGraphicsImageRender을 제공 합니다.

... 색심도 및 이미지 스케일과 같은 구성을 처리하거나 코어 그래픽 컨텍스트를 관리하지 않고도 그리기 작업을 수행합니다.

애플 컴퓨터 코리아-UIGraphicsImageRenderer

이제 다음과 같이 할 수 있습니다 :

let renderer = UIGraphicsImageRenderer(size: someView.bounds.size)

let image = renderer.image(actions: { context in
    someView.drawHierarchy(in: someView.bounds, afterScreenUpdates: true)
})

여기에 많은 답변이 대부분의 경우 저에게 효과적이었습니다. 그러나의 스냅 샷을 만들려고 할 때 ARSCNView위에 설명한 방법으로 만 수행 할 수있었습니다. 현재로서는 ARKit은 아직 베타 버전이고 Xcode는 베타 4 버전이라는 점은 주목할 가치가 있습니다.


7

스크린 샷을 저장하고 스크린 샷도 반환합니다.

-(UIImage *)capture{
    UIGraphicsBeginImageContext(self.view.bounds.size);
    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *imageView = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    UIImageWriteToSavedPhotosAlbum(imageView, nil, nil, nil); //if you need to save
    return imageView;
}

5

다음 스 니펫이 전체 화면을 원한다면 ( 상태 표시 줄 제외 ) 필요한 경우 AppDelegate를 앱 대리자 이름으로 바꾸십시오.

- (UIImage *)captureFullScreen {

    AppDelegate *_appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;

    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
        // for retina-display
        UIGraphicsBeginImageContextWithOptions(_appDelegate.window.bounds.size, NO, [UIScreen mainScreen].scale);
        [_appDelegate.window drawViewHierarchyInRect:_appDelegate.window.bounds afterScreenUpdates:NO];
    } else {
        // non-retina-display
        UIGraphicsBeginImageContext(_bodyView.bounds.size);
        [_appDelegate.window drawViewHierarchyInRect:_appDelegate.window.bounds afterScreenUpdates:NO];
    }

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

마지막으로 탐색 모음을 추가하는 것! 내가 할 수 있다면 두 번 투표 할 것입니다! 건배 친구
marcelosarquis

4

Swift 3 구현으로 답변을 찾을 수 없습니다. 그래서 여기에 간다.

static func screenshotOf(window: UIWindow) -> UIImage? {

    UIGraphicsBeginImageContextWithOptions(window.bounds.size, true, UIScreen.main.scale)

    guard let currentContext = UIGraphicsGetCurrentContext() else {
        return nil
    }

    window.layer.render(in: currentContext)
    guard let image = UIGraphicsGetImageFromCurrentImageContext() else {
        UIGraphicsEndImageContext()
        return nil
    }

    UIGraphicsEndImageContext()
    return image
}

3

iOS 7.0 이상

view say (myView) 스크린 샷을 만들려면 한 줄로 수행 할 수 있습니다.

[myView snapshotViewAfterScreenUpdates:NO];

3

이것은 swift 4.2 에서 작동 하며 스크린 샷은 라이브러리에 저장되지만 다음을 편집하는 것을 잊지 마십시오 info.plist @ NSPhotoLibraryAddUsageDescription.

  @IBAction func takeScreenshot(_ sender: UIButton) {

    //Start full Screenshot
    print("full Screenshot")
    UIGraphicsBeginImageContext(card.frame.size)
    view.layer.render(in: UIGraphicsGetCurrentContext()!)
    var sourceImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    UIImageWriteToSavedPhotosAlbum(sourceImage!, nil, nil, nil)

    //Start partial Screenshot
    print("partial Screenshot")
    UIGraphicsBeginImageContext(card.frame.size)
    sourceImage?.draw(at: CGPoint(x:-25,y:-100)) //the screenshot starts at -25, -100
    var croppedImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    UIImageWriteToSavedPhotosAlbum(croppedImage!, nil, nil, nil)

}

2

보기에서 스크린 샷 가져 오기

-(UIImage *)getScreenshotImage {
    if ([[UIScreen mainScreen] scale] == 2.0) {
        UIGraphicsBeginImageContextWithOptions(self.view.frame.size, FALSE, 2.0);
    } else {
        UIGraphicsBeginImageContextWithOptions(self.view.frame.size, FALSE, 1.0);
    }

    [self.view.window.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage * result = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return result;
}

사진을 이미지로 저장

UIImageWriteToSavedPhotosAlbum(YOUR_IMAGE, nil, nil, nil);

어떻게

UIImageWriteToSavedPhotosAlbum([self getScreenshotImage], nil, nil, nil);

2

보기에서 스크린 샷 가져 오기 :

- (UIImage *)takeSnapshotView {
    CGRect rect = [myView bounds];//Here you can change your view with myView
    UIGraphicsBeginImageContextWithOptions(rect.size,YES,0.0f);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [myView.layer renderInContext:context];
    UIImage *capturedScreen = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return capturedScreen;//capturedScreen is the image of your view
}

희망, 이것이 당신이 찾고있는 것입니다. 어떤 걱정이라도 나에게 돌아온다. :)


2

나는이 질문에 크게 보았으므로 대답하고 있으며 거기에는 많은 답변이 있으며 Swift와 Obj-C가 있습니다.

면책 조항 이것은 내 코드 도 아니고 답도 아닙니다 . 여기에 착륙 한 사람들이 빠른 답변을 찾도록 돕기위한 것입니다. 크레디트가 예정된 곳에서 크레디트를 제공하는 원래 답변에 대한 링크가 있습니다! 답변을 사용하는 경우 원래 답변을 +1로 존중하십시오!


사용 QuartzCore

#import <QuartzCore/QuartzCore.h> 

if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
    UIGraphicsBeginImageContextWithOptions(self.window.bounds.size, NO, [UIScreen mainScreen].scale);
} else {
    UIGraphicsBeginImageContext(self.window.bounds.size);
}

[self.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *imageData = UIImagePNGRepresentation(image);
if (imageData) {
    [imageData writeToFile:@"screenshot.png" atomically:YES];
} else {
    NSLog(@"error while taking screenshot");
}

스위프트에서

func captureScreen() -> UIImage
{

    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, false, 0);

    self.view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)

    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()

    UIGraphicsEndImageContext()

    return image
}

참고 : 프로그래밍의 특성상 업데이트가 필요할 수 있으므로 수정하거나 알려주십시오! * 또한 포함 할 가치가있는 답변 / 방법을 포함시키지 못한 경우 언제든지 알려주십시오!


1
이 답변은 아무것도 추가하지 않는 것 같습니다. 이미 페이지에있는 두 개의 답변을 복사하여 붙여 넣고 결과를 자신의 것으로 게시했습니다.
user2357112는

내 의도는 그들의 답변에 대한 신용을 얻지 않는 것이 었습니다. 신속한 답변과 Obj-C를 하나의 답변에 포함시켜 사람들이 더 빨리 찾을 수있었습니다. 해당 답변도 참조했습니다. 이 작업을 수행하지 않으면 답변을 삭제하고 그 중 하나로 되돌아갑니다.

ObjC 솔루션을 사용하고 있습니다. 나를 위해 "self"뒤에 ".view"를 추가해야했지만 결과는 100 %입니다. 이것은 금입니다
samouray

프레젠테이션 스트림 캡처에서도 일했습니다. 감사합니다
YSR 팬

1

다른 옵션은 계측기에서 자동화 도구를 사용하는 것입니다. 스크립트를 작성하여 원하는 상태로 화면을 배치 한 다음 사진을 찍습니다. 여기 내 앱 중 하나에 사용한 스크립트가 있습니다. 분명히, 스크립트의 세부 사항은 앱마다 다릅니다.

var target = UIATarget.localTarget();
var app = target.frontMostApp();
var window = app.mainWindow();
var picker = window.pickers()[0];
var wheel = picker.wheels()[2];
var buttons = window.buttons();
var button1 = buttons.firstWithPredicate("name == 'dateButton1'");
var button2 = buttons.firstWithPredicate("name == 'dateButton2'");

function setYear(picker, year) {
    var yearName = year.toString();
    var yearWheel = picker.wheels()[2];
    yearWheel.selectValue(yearName);
}

function setMonth(picker, monthName) {
    var wheel = picker.wheels()[0];
    wheel.selectValue(monthName);
}

function setDay(picker, day) {
    var wheel = picker.wheels()[1];
    var name = day.toString();
    wheel.selectValue(name);
}

target.delay(1);
setYear(picker, 2015);
setMonth(picker, "July");
setDay(picker, 4);
button1.tap();
setYear(picker, 2015);
setMonth(picker, "December");
setDay(picker, 25);

target.captureScreenWithName("daysShot1");

var nButtons = buttons.length;
UIALogger.logMessage(nButtons + " buttons");
for (var i=0; i<nButtons; i++) {
    UIALogger.logMessage("button " + buttons[i].name());
}

var tabBar = window.tabBars()[0];
var barButtons = tabBar.buttons();

var nBarButtons = barButtons.length;
UIALogger.logMessage(nBarButtons + " buttons on tab bar");

for (var i=0; i<nBarButtons; i++) {
    UIALogger.logMessage("button " + barButtons[i].name());
}

var weeksButton = barButtons[1];
var monthsButton = barButtons[2];
var yearsButton = barButtons[3];

target.delay(2);
weeksButton.tap();
target.captureScreenWithName("daysShot2");
target.delay(2);
monthsButton.tap();
target.captureScreenWithName("daysShot3");
target.delay(2);
yearsButton.tap();
target.delay(2);
button2.tap();
target.delay(2);
setYear(picker, 2018);
target.delay(2);
target.captureScreenWithName("daysShot4");

1

다음 사이트에서 두 가지 옵션을 사용할 수 있습니다.

옵션 1 : UIWindow 사용 (시도하고 완벽하게 작동)

// create graphics context with screen size
CGRect screenRect = [[UIScreen mainScreen] bounds];
UIGraphicsBeginImageContext(screenRect.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
[[UIColor blackColor] set];
CGContextFillRect(ctx, screenRect);

// grab reference to our window
UIWindow *window = [UIApplication sharedApplication].keyWindow;

// transfer content into our context
[window.layer renderInContext:ctx];
UIImage *screengrab = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

옵션 2 : UIView 사용

// grab reference to the view you'd like to capture
UIView *wholeScreen = self.splitViewController.view;

// define the size and grab a UIImage from it
UIGraphicsBeginImageContextWithOptions(wholeScreen.bounds.size, wholeScreen.opaque, 0.0);
[wholeScreen.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *screengrab = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

망막 스크린 용 (DenNukem 답변)

// grab reference to our window
    UIWindow *window = [UIApplication sharedApplication].keyWindow;

    // create graphics context with screen size
    CGRect screenRect = [[UIScreen mainScreen] bounds];
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
        UIGraphicsBeginImageContextWithOptions(screenRect.size, NO, [UIScreen mainScreen].scale);
    } else {
        UIGraphicsBeginImageContext(screenRect.size);
        [window.layer renderInContext:UIGraphicsGetCurrentContext()];
    }

자세한 내용은 http://pinkstone.co.uk/how-to-take-a-screeshot-in-ios-programmatically/


1

작은 기여만으로 버튼 으로이 작업을 수행했지만 버튼을 누르면 버튼이 캡처되었음을 의미합니다. 먼저 강조 표시를 해제합니다.

- (IBAction)screenShot:(id)sender {
    // Unpress screen shot button
    screenShotButton.highlighted = NO;

    // create graphics context with screen size
    CGRect screenRect = [[UIScreen mainScreen] bounds];

    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
        UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, [UIScreen mainScreen].scale);
    } else {
        UIGraphicsBeginImageContext(self.view.bounds.size);
    }

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [[UIColor blackColor] set];
    CGContextFillRect(ctx, screenRect);

    // grab reference to our window
    UIWindow *window = [UIApplication sharedApplication].keyWindow;

    // transfer content into our context
    [window.layer renderInContext:ctx];
    UIImage *screengrab = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    // save screengrab to Camera Roll
    UIImageWriteToSavedPhotosAlbum(screengrab, nil, nil, nil);
}

코드 1의 본문을 얻었습니다 .http : //pinkstone.co.uk/how-to-take-a-screeshot-in-ios-programmatically/ 옵션 1을 사용한 곳에서 옵션 2가 작동하지 않는 것 같습니다 나를 위해. 이 스레드에서 Rentina 화면 크기 조정 및 screenShotButton 강조 표시를 추가했습니다. 내가 사용하는보기는 버튼과 레이블이있는 스토리 보드 화면이며 나중에 프로그램을 통해 여러 UIView가 추가되었습니다.


편집 해 주셔서 감사합니다. 나는 주석이 달린 코드에 남겨 두었다는 것을 깨달았지만 "그러면 붙여 넣은 코드가 얼마나 진짜인지"라고 생각했습니다. 현재 App Store에있는 라이브 작업 코드
Symanski

1

Swift에서는 다음 코드를 사용할 수 있습니다.

if UIScreen.mainScreen().respondsToSelector(Selector("scale")) {
    UIGraphicsBeginImageContextWithOptions(self.window!.bounds.size, false, UIScreen.mainScreen().scale)
}
else{
    UIGraphicsBeginImageContext(self.window!.bounds.size)
}
self.window?.layer.renderInContext(UIGraphicsGetCurrentContext())
var image : UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)

0

스위프트 4 :

func makeImage(withView view: UIView) -> UIImage? {

    let rect = view.bounds

    UIGraphicsBeginImageContextWithOptions(rect.size, true, 0)

    guard let context = UIGraphicsGetCurrentContext() else {
      assertionFailure()
      return nil
    }

    view.layer.render(in: context)

    guard let image = UIGraphicsGetImageFromCurrentImageContext() else {
      assertionFailure()
      return nil
    }

    UIGraphicsEndImageContext()

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