代码之家  ›  专栏  ›  技术社区  ›  JP Richardson

在iPhone模拟器上自动截图?

  •  26
  • JP Richardson  · 技术社区  · 15 年前

    每当我为iPhone应用程序更改用户界面时,我都厌倦了拍摄新的屏幕截图。我希望能够运行一个脚本/程序/任何东西,将我的二进制文件加载到模拟器上,然后进行一些截屏。

    解决方案可以是任何语言…对我来说没关系。

    谢谢!

    6 回复  |  直到 12 年前
        1
  •  24
  •   mohsenr    14 年前

    有了iPhone SDK4,您可以自动执行GUI测试,并且可以为您截屏。

    基本上,你编写一个javascript脚本,然后仪器(使用自动化模板)可以在设备上运行它来测试用户界面,并且可以记录数据、屏幕截图等,还可以警告是否有东西坏了。

    我找不到它的参考指南,但在SDK参考库中搜索 UIA* 类(类) UIAElement )

    还有一个视频演示了来自WWDC第306部分的内容。

        2
  •  12
  •   Offe    15 年前

    我也有同样的愿望。我想能够保存一些屏幕截图在我的应用程序没有所有的手动工作。我还没到,但我已经开始了。

    其思想是跟踪/var/log/system.log,从nslog语句输出到这里。我将输出通过管道传输到python程序。python程序从stdin读取所有行,当该行与特定模式匹配时,它调用screencapture。

    NSLog(@"screenshot mainmenu.png");
    

    这将导致一个名为“XX”的屏幕截图。mainmenu yy.png“每次调用时创建。xx是程序启动后的屏幕截图编号。YY是“主菜单”屏幕截图的编号。

    我甚至添加了一些不必要的功能:

    NSLog(@"screenshot -once mainmenu.png");
    

    这只会保存“XX”。mainmenu.png“一次。

    NSLog(@"screenshot -T 4 mainmenu.png");
    

    这将在延迟4秒后进行屏幕截图。

    运行具有正确日志记录的应用程序后,可以创建具有以下名称的屏幕截图:

    00. SplashScreen.png
    01. MainMenu 01.png
    03. StartLevel 01.png
    04. GameOver 01.png
    05. MainMenu 02.png
    

    试一试:

    1. 向代码中添加一些nslog语句

    2. $tail-f-n0/var/log/system.log/grab.py

    3. 在模拟器中启动iPhone应用程序

    4. 用你的应用玩

    5. 看看屏幕截图,显示你在哪里开始了grab.py程序。

    grab.py:

    #!/usr/bin/python
    
    import re
    import os
    from collections import defaultdict
    
    def screenshot(filename, select_window=False, delay_s=0):
        flags = []
        if select_window:
            flags.append('-w')
        if delay_s:
            flags.append('-T %d' % delay_s)
        command_line = 'screencapture %s "%s"' % (' '.join(flags), filename)
        #print command_line
        os.system(command_line)
    
    def handle_line(line, count=defaultdict(int)):
        params = parse_line(line)
        if params:
            filebase, fileextension, once, delay_s = params
            if once and count[filebase] == 1:
                print 'Skipping taking %s screenshot, already done once' % filebase
            else:
                count[filebase] += 1
                number = count[filebase]
                count[None] += 1
                global_count = count[None]
                file_count_string = (' %02d' % number) if not once else ''
    
                filename = '%02d. %s%s.%s' % (global_count, filebase, file_count_string, fileextension)
                print 'Taking screenshot: %s%s' % (filename, '' if delay_s == 0 else (' in %d seconds' % delay_s))
                screenshot(filename, select_window=False, delay_s=delay_s)
    
    def parse_line(line):
        expression = r'.*screenshot\s*(?P<once>-once)?\s*(-delay\s*(?P<delay_s>\d+))?\s*(?P<filebase>\w+)?.?(?P<fileextension>\w+)?'
        m = re.match(expression, line)
        if m:
            params = m.groupdict()
            #print params
            filebase = params['filebase'] or 'screenshot'
            fileextension = params['fileextension'] or 'png'
            once = params['once'] is not None
            delay_s = int(params['delay_s'] or 0)
            return filebase, fileextension, once, delay_s
        else:
            #print 'Ignore: %s' % line
            return None
    
    def main():
        try:
            while True:
                handle_line(raw_input())
        except (EOFError, KeyboardInterrupt):
            pass
    
    if __name__ == '__main__':
        main()
    

    此版本的问题:

    如果只想截取iPhone模拟器窗口的屏幕截图,则必须为每个屏幕截图单击iPhone模拟器窗口。屏幕捕获拒绝捕获单个窗口,除非您愿意与之交互,这是命令行工具的一个奇怪的设计决策。

    更新: 现在iPhone Simulator Cropper(位于 http://www.curioustimes.de/iphonesimulatorcropper/index.html )从命令行工作。因此,不要使用内置的截屏,而是下载并使用它。所以现在这个过程是完全自动的。

        3
  •  7
  •   Tom H    14 年前

    在iPhone模拟器中,有一个“复制屏幕”菜单项。按住Control键时,它将替换“编辑”菜单中的“复制”菜单项。 按键为ctrl-cmd-c 一个简单的applescript可以复制屏幕截图并保存它。有点像(对我有用,即使它 哈基):

    tell application "iPhone Simulator" to activate
    tell application "System Events"
        keystroke "c" using {command down, control down}
    end tell
    tell application "Preview" to activate
    tell application "System Events"
        keystroke "n" using {command down}
        keystroke "w" using {command down}
        delay 1
        keystroke return
        delay 1
        keystroke "File Name"
        keystroke return
    end tell
    

    如果你不明白,请评论…

        4
  •  6
  •   rpetrich    15 年前

    私人 UIGetScreenImage(void) API可用于捕获屏幕内容:

    CGImageRef UIGetScreenImage();
    void SaveScreenImage(NSString *path)
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        CGImageRef cgImage = UIGetScreenImage();
        void *imageBytes = NULL;
        if (cgImage == NULL) {
            CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
            imageBytes = malloc(320 * 480 * 4);
            CGContextRef context = CGBitmapContextCreate(imageBytes, 320, 480, 8, 320 * 4, colorspace, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big);
            CGColorSpaceRelease(colorspace);
            for (UIWindow *window in [[UIApplication sharedApplication] windows]) {
                CGRect bounds = [window bounds];
                CALayer *layer = [window layer];
                CGContextSaveGState(context);
                if ([layer contentsAreFlipped]) {
                    CGContextTranslateCTM(context, 0.0f, bounds.size.height);
                    CGContextScaleCTM(context, 1.0f, -1.0f);
                }
                [layer renderInContext:(CGContextRef)context];
                CGContextRestoreGState(context);
            }
            cgImage = CGBitmapContextCreateImage(context);
            CGContextRelease(context);
        }
        NSData *pngData = UIImagePNGRepresentation([UIImage imageWithCGImage:cgImage]);
        CGImageRelease(cgImage);
        if (imageBytes)
            free(imageBytes);
        [pngData writeToFile:path atomically:YES];
        [pool release];
    }
    

    一定要把它包在 #ifdef 所以它不会出现在发布版本中。

        5
  •  1
  •   KrauseFx    12 年前

    如果您对自动更改模拟器语言和设备类型感兴趣,我开发了一些这样做的脚本: http://github.com/toursprung/iOS-Screenshot-Automator

        6
  •  0
  •   Michael Kessler    14 年前

    您也可以使用一些屏幕捕获应用程序来捕获模拟器屏幕上的视频。

    我经常使用Jing应用程序。

    我甚至用它发送一个视频,向客户展示应用程序…