如何通过编程方式对iPhone进行屏幕截图?

14

在Objective-C中,我们能否截取屏幕并将此图像存储在UIImage中?


1
可能是重复问题 https://dev59.com/4nE95IYBdhLWcg3wp_qn - AndersK
1
可能是重复的问题:如何以编程方式进行屏幕截图 - Brad Larson
11个回答

25

前面的代码假设要捕获的视图位于主屏幕上,但实际上可能不是。

这样做是否能始终捕获主窗口的内容?(警告:编译自StackOverflow)


- (UIImage *) captureScreen {
    UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
    CGRect rect = [keyWindow bounds];
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [keyWindow.layer renderInContext:context];   
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

1
我在视图中制作了动画图形,但是这段代码忽略了动画(动画完成后未被移除)。 - Tibidabo
谢谢!这是我迄今为止找到的最简单的方法。 - Greg
2
那不起作用:状态栏没有保存,而我的一个视图是OpenGL视图,它的内容也没有保存。 - Jean-Denis Muys

17

您需要创建一个大小与您的屏幕相同的位图上下文,然后使用该上下文在其中绘制内容。

[self.view.layer renderInContext:c]

将你的视图复制到其中。完成后,您可以使用

CGBitmapContextCreateImage(c)

从您的上下文中创建CGImage。

说明:

CGSize screenSize = [[UIScreen mainScreen] applicationFrame].size;
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); 
CGContextRef ctx = CGBitmapContextCreate(nil, screenSize.width, screenSize.height, 8, 4*(int)screenSize.width, colorSpaceRef, kCGImageAlphaPremultipliedLast);
CGContextTranslateCTM(ctx, 0.0, screenSize.height);
CGContextScaleCTM(ctx, 1.0, -1.0);

[(CALayer*)self.view.layer renderInContext:ctx];

CGImageRef cgImage = CGBitmapContextCreateImage(ctx);
UIImage *image = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);
CGContextRelease(ctx);  
[UIImageJPEGRepresentation(image, 1.0) writeToFile:@"screen.jpg" atomically:NO];

请注意,如果您在响应UIButton的点击运行代码,则您的图片将显示该按钮已按下。


你能在这里详细说明一下吗?谢谢。 - user12345
只是想提一下,您错过了释放colorSpaceRef。 - Patrick Hernandez
1
另外,什么是 self?窗口变换呢?你知不知道当键盘/警报显示时会发生什么? - Sulthan

7

1
谢谢。对于这个苹果资源点赞。 - Mikayil Abdullayev
1
链接失效了 :-( - noelicus

3

试试这个...

- (UIImage*)captureView:(UIView *)view 
{
    CGRect rect = [[UIScreen mainScreen] bounds];
    UIGraphicsBeginImageContext(rect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [view.layer renderInContext:context];
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

- (void)saveScreenshotToPhotosAlbum:(UIView *)view 
{
    UIImageWriteToSavedPhotosAlbum([self captureView:self.view], nil, nil,nil);
}

2

// 100% 工作

- (UIImage *)screenshot
{                   
  UIGraphicsBeginImageContextWithOptions(self.main_uiview.bounds.size, NO, 2.0f);
  [self.main_uiview drawViewHierarchyInRect:_main_uiview.bounds afterScreenUpdates:YES];

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

  return image;
}

2
UIGraphicsBeginImageContext(self.window.bounds.size);
[self.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData * data = UIImagePNGRepresentation(image);
[data writeToFile:@"foo.png" atomically:YES];

2011年4月更新:对于视网膜显示屏,请将第一行更改为以下内容:

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

1
- (void)SnapShot {
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
        UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, [UIScreen mainScreen].scale);
    } else {
        UIGraphicsBeginImageContext(self.view.bounds.size);
    }
    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];

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

    NSData *data = UIImagePNGRepresentation(image);
    [data writeToFile:@"snapshot.png" options:NSDataWritingWithoutOverwriting error:Nil];
    [data writeToFile:@"snapshot.png" atomically:YES];

    UIImageWriteToSavedPhotosAlbum([UIImage imageWithData:data], nil, nil, nil);
}

  1. 你对文件进行了双重写入。
  2. 如果你已经有图像对象,为什么还需要[UIImage imageWithData:data]
  3. 驼峰命名法。
- Alex Nazarov

0

现代方式:

Obj-C

@interface UIView (Snapshot)
- (UIImage * _Nullable)snapshot;
@end

@implementation UIView (Snapshot)

- (UIImage * _Nullable)snapshot {
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, UIScreen.mainScreen.scale);
    [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

@end

Swift

extension UIView {
    func snapshot() -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.main.scale)
        drawHierarchy(in: bounds, afterScreenUpdates: true)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
   }
}

0
使用以下代码进行屏幕截图:
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
UIGraphicsBeginImageContext(self.webView.bounds.size);

    [self.webView.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage *screenshotImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    UIImageWriteToSavedPhotosAlbum(screenshotImage, nil, nil, nil);

    NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];


    NSString *str1=[NSString stringWithFormat:@"%d",myInt];

    NSString *pngFilePath = [NSString stringWithFormat:@"%@/page_%@.png",docDir,str1]; // any name u want for image
    NSLog(@"%@",pngFilePath);
    NSData *data1 = [NSData dataWithData:UIImagePNGRepresentation(screenshotImage)]; 
    [data1 writeToFile:pngFilePath atomically:YES];
}

你为什么需要 data1UIImagePNGRepresentation 已经是 NSData 了。 - Alex Nazarov

0
  • (UIImage *)screenshot { UIGraphicsBeginImageContextWithOptions(self.main_uiview.bounds.size, NO, 2.0f); [self.main_uiview drawViewHierarchyInRect:_main_uiview.bounds afterScreenUpdates:YES];

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

    return image; }

  • (UIImage *)截屏 { UIGraphicsBeginImageContextWithOptions(self.main_uiview.bounds.size, NO, 2.0f); [self.main_uiview drawViewHierarchyInRect:_main_uiview.bounds afterScreenUpdates:YES];

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

    return image; }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接