Я хочу, чтобы скриншот изображения на экране сохранялся в сохраненной библиотеке фотографий.
Как сделать снимок экрана программно на iOS
Ответ 1
Я отвечаю на этот вопрос, так как он высоко ценится, и есть много ответов, а также Swift и Obj-C.
Отказ от ответственности Это не мой кодекс и не мои ответы, это только для того, чтобы помочь людям, находящимся здесь, найти быстрый ответ. Есть ссылки на оригинальные ответы, чтобы дать кредит, где кредит должен !! Пожалуйста, отметьте это +1, если вы используете их ответ!
#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
}
Примечание: Как и в случае с программированием, обновления могут потребоваться, поэтому, пожалуйста, отредактируйте или дайте мне знать! * Кроме того, если я не смог включить ответ/метод, который стоит включить, не стесняйтесь, дайте мне знать!
Ответ 2
С учетом проверки отображения сетчатки используйте следующий фрагмент кода:
#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");
}
Ответ 3
Ниже метод работает для объектов 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;
}
Ответ 4
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];
Ответ 5
- (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 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);  
}
Ответ 6
Смотрите этот, похоже, вы можете использовать UIGetScreenImage().
Ответ 7
В SWIFT
func captureScreen() -> UIImage
{
    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, false, 0);
    self.view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image
}
Ответ 8
 Начиная с iOS10, это становится немного проще. UIKit поставляется с UIGraphicsImageRender который позволяет вам
... выполнять задачи рисования, не обращаясь к конфигурации, такой как глубина цвета и масштаб изображения, или управляя контекстами Core Graphics
Документы Apple - 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.
Ответ 9
Это сохранит скриншот, а также вернет скриншот.
-(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;
}
Ответ 10
Я думаю, что следующий фрагмент поможет, если вы хотите сделать полный экран (за исключением строки состояния), просто замените 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;
}
Ответ 11
Я не смог найти ответ с реализацией 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
}
Ответ 12
Для iOS 7.0 или выше..
Если вы хотите сделать скриншоты вида say (myView), вы можете сделать это с помощью одной строки:
[myView snapshotViewAfterScreenUpdates:NO];
Ответ 13
Получить снимок экрана из представления
-(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);
How-To
UIImageWriteToSavedPhotosAlbum([self getScreenshotImage], nil, nil, nil);
Ответ 14
Получить снимок экрана из вида:
- (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
}
Надеюсь, это то, что вы ищете. Меня волнует любая забота.:)
Ответ 15
 Это будет работать с 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)
}
Ответ 16
Другой вариант - использовать инструмент "Автоматизация" на инструментах. Вы пишете script, чтобы поместить экран в то, что вы хотите, а затем сделайте снимки. Вот script, который я использовал для одного из моих приложений. Очевидно, что детали script будут отличаться для вашего приложения.
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");
Ответ 17
Небольшой вклад, я сделал это с помощью кнопки, но нажатие также означает, что нажата кнопка. Поэтому сначала я не рассмеялся.
- (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);
}
Я получил основную часть кода: http://pinkstone.co.uk/how-to-take-a-screeshot-in-ios-programmatically/ где я использовал вариант 1, вариант 2, похоже, не работал у меня. Добавлены корректировки размеров экрана Rentina из этой темы и неосведомленности экранаShotButton. Представление, в котором я его использую, - это экран кнопок и надписей StoryBoarded с несколькими UIView, добавленными позже через программу.
Ответ 18
Два варианта доступны на следующем сайте:
ВАРИАНТ 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/
Ответ 19
В 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)
Ответ 20
Swift 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
}
