İOS'ta programlı olarak ekran görüntüsü nasıl alınır


157

Ekrandaki görüntünün kaydedilen fotoğraf kitaplığına kaydedilmesini istiyorum.

Yanıtlar:


233

Retina ekranı için bir kontrol düşünürken aşağıdaki kod snippet'ini kullanın:

#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
Bunun OpenGL ES katmanları gibi belirli ekran içeriği türlerini yakalamayacağını unutmayın. Hua-Ying'in işaret ettiği UIGetScreenImage ().
Brad Larson

12
Sevgili insanlar, #import <QuartzCore / QuartzCore.h> yapmayı unutmayın
Enrico Susatyo

uygulamanızın henüz çektiği bir resmi görüntülüyorsanız bu ekran görüntüsü alacak mı?
John Riselvato

5
Bu resim nerede saklanıyor?
Burhanuddin Sunelwala

3
@ wladimir-palant: Key-Board'a ne dersin, sceen'in ekran görüntüsünü almak için kullandığımda kullanıcı türünün, o zaman tuş kartının yakalanmadığı durumlarda, ekran yakalamada nasıl anahtar tahtası ekleyebilirim?
g212gs

46

Aşağıdaki yöntem OPENGL nesneleri için de çalışır

//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özel bir API olduğunu
jonahb

Bunun için çok teşekkürler! Kesinlikle oyumu alırsın. Başka birçok yol denedikten sonra, javafx kullanıcı arabirimi ile robovm'de ekran yakalamanın nasıl alınabileceğinin tek yolu drawViewHierarchy'nin olduğu görülmektedir.
Christo Smal

Bu her şey çalışıyor !!!! Ekranda çok sayıda 3d dönüşümüm var ve diğer çözümler ekran görüntümde karışıklık yarattı. Bu olması gerektiği gibi çalışıyor. Çok teşekkürler!
AndrewK

1
görünüm denetleyicisi bir gezinme denetleyicisindeyse gezinme çubuğu yakalanmaz
Radu Simionescu

Evet, drawViewHierarchyInRect renderInContext :-) 'dan daha hızlı
alones

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 kullanma hakkında not için. Kayıpsızdır ve kalite = 1.0 ile jpeg'den daha küçük olacaktır.
Rob

1
boş alan bırakmak yerine iOS 7'de NavigationBar kullanmıyor.
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);  
}

Kaynak .


1
MyDataLength neden 4 ontop 320 * 480 ile çarpılır?
Jab

2
Bu da bize bunu yapmanın daha kolay bir yolunu sunmadıkları için çok aptalca görünüyor.
Jab

320 * 480 piksel sayısıdır. Dört kez, böylece her piksel için RGBA'ya sahip olursunuz.
Aistina

bir iPhone 4 üzerinde çalışırken ölçek faktörü ile
katlamayı unutmayın

1
@Aistina, kullan UIImage *myImage = [[UIImage alloc] initWithCGImage:imageRef scale:1.0 orientation:UIImageOrientationDownMirrored];ve artık ' buffer2'ye ihtiyacın yok. BTW bellek yönetimi hakkında unuttuğunuz gibi görünüyor, ücretsiz () veya release () çağrı yok ...
Oleg Trakhman

10

SWIFT'TA

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

İOS10'dan itibaren, bu biraz daha basitleşiyor. İle UIKit geliyor UIGraphicsImageRendero yapmanızı sağlar

... renk derinliği ve görüntü ölçeği gibi yapılandırmaları işlemek veya Çekirdek Grafik bağlamlarını yönetmek zorunda kalmadan çizim görevlerini yerine getirmek

Apple Dokümanlar - UIGraphicsImageRenderer

Şimdi böyle bir şey yapabilirsiniz:

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

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

Buradaki cevapların çoğu benim için çoğu durumda çalıştı. Ancak bir anlık görüntüsünü almaya çalışırken ARSCNView, bunu yalnızca yukarıda açıklanan yöntemi kullanarak yapabildim. Şu anda ARKit'in hala beta ve Xcode'un beta 4'te olduğunu belirtmek gerekir.


7

Bu, bir ekran görüntüsünü kaydeder ve ekran görüntüsünü de döndürür.

-(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

Tam snippet'i ( durum çubuğu hariç) almak istiyorsanız aşağıdaki snippet'in yardımcı olacağını düşünüyorum, gerekirse AppDelegate'i uygulama temsilcisi adınızla değiştirin.

- (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;
}

Nihayetinde gezinme çubuğunu ekleyen bir tane! Eğer iki kez oy! Şerefe dostum
marcelosarquis

4

Swift 3 uygulamasıyla bir cevap bulamadım. İşte gidiyor.

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

İOS 7.0 veya üstü için ..

View say (myView) ekran görüntülerini almak istiyorsanız, bunu tek satırla yapabilirsiniz:

[myView snapshotViewAfterScreenUpdates:NO];

3

Bu, hızlı 4.2 ile çalışacak , ekran görüntüsü kitaplığa kaydedilecek, ancak lütfen info.plist @ NSPhotoLibraryAddUsageDescriptionşunları düzenlemeyi unutmayın :

  @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

Görünümden Ekran Görüntüsü Alın

-(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;
}

Resmi Fotoğraflara Kaydet

UIImageWriteToSavedPhotosAlbum(YOUR_IMAGE, nil, nil, nil);

Nasıl

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

2

Görünümden Ekran Görüntüsü Alın:

- (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
}

Umarım aradığınız şey budur. Herhangi bir endişeniz bana geri dönüyor. :)


2

Bu soruyu çokça görüldüğü için cevaplıyorum ve orada birçok cevap var, ayrıca Swift ve Obj-C var.

Feragatname Bu benim kodum ya da cevaplarım değil, sadece buraya gelen insanların hızlı bir cevap bulmasına yardımcı olmak içindir. Kredi vadesinde kredi vermek için orijinal cevaplar bağlantıları vardır !! Eğer cevaplarını kullanırsanız orijinal cevapları +1 ile onurlandırın!


kullanma 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");
}

Swift'te

func captureScreen() -> UIImage
{

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

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

    let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()

    UIGraphicsEndImageContext()

    return image
}

Not: Programlama ile birlikte, güncellemelerin yapılması gerekebilir, bu yüzden lütfen düzenleyin veya bana bildirin! * Ben de dahil bir değer / yöntem dahil etmek başarısız olsaydı da bana bildirmekten çekinmeyin!


1
Bu cevap hiçbir şey eklemiyor gibi görünüyor. Zaten sayfada bulunan cevapların ikisini kopyalayıp yapıştırdınız ve sonucu kendiniz olarak yayınladınız.
user2357112 Monica

Niyetim cevapları için kredi almak değildi, tek bir cevaba hem hızlı hem de Obj-C'yi dahil etmekti, bu yüzden insanların bulması daha hızlıydı. Ben de karşılık gelen cevaplara değindim. bu yapılmazsa cevabımı silerim ve bunlardan sadece birine geri dönerim.
Jab

ObjC çözümünü kullanıyorum. Benim için, "self" den sonra ".view" eklemeliydim, ama sonuç% 100. Bu ALTIN
samouray

Sunum Akışı Yakalama için de çalıştı. Teşekkürler
YSR fan

1

Diğer bir seçenek ise Otomasyon aracını cihazlarda kullanmaktır. Ekranı istediğiniz herhangi bir duruma koymak için bir komut dosyası yazıyorsunuz, sonra çekimleri yapıyorsunuz. İşte uygulamalarımdan biri için kullandığım komut dosyası. Açıkçası, komut dosyasının ayrıntıları uygulamanız için farklı olacaktır.

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

Körük yerinde iki seçenek vardır:

SEÇENEK 1: UIWindow kullanma (denendi ve mükemmel çalıştı)

// 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();

SEÇENEK 2: UIView kullanma

// 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();

Retina ekranı için (DenNukem cevabı olarak)

// 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()];
    }

daha fazla ayrıntı için: http://pinkstone.co.uk/how-to-take-a-screeshot-in-ios-programmatically/


1

Sadece küçük bir katkı, bunu bir düğmeyle yaptım ama basmak da düğmenin basıldığı anlamına geliyor. İlk önce vurgulamıyorum.

- (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);
}

Kodun ana gövdesini şu adresten aldım: http://pinkstone.co.uk/how-to-take-a-screeshot-in-ios-programmatically/ burada 1. seçeneği kullandım, seçenek 2 işe yaramadı benim için. Bu iş parçacığındaki Rentina ekran boyutları ve screenShotButton'un aydınlatılmaması için düzenlemeler eklendi. Üzerinde kullandığım görünüm, düğmelerin ve etiketlerin bir StoryBoarded ekranıdır ve daha sonra program aracılığıyla birkaç UIView eklenmiştir.


Düzenleme için teşekkürler. Ben yorum kodu bırakmıştı, ama sonra "yapıştırılan kod bu kadar gerçek" olduğunu düşündüm. App Store'da bulunan canlı çalışma kodu.
Symanski

1

Swift'te aşağıdaki kodu kullanabilirsiniz.

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

Hızlı 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
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.