1

This code used to work, however I think Xcode's new ARC may have killed it

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    CGDirectDisplayID displayID = CGMainDisplayID();
    CGImageRef image = CGDisplayCreateImage(displayID); //this is a screenshot (works fine)
    [self savePNGImage:image path:@"~/Desktop"];
}


-(void)savePNGImage:(CGImageRef)imageRef path:(NSString *)path {
    NSURL *outURL = [[NSURL alloc] initFileURLWithPath:path]; 
    //here xcode suggests using __bridge for CFURLRef?
    CGImageDestinationRef dr = CGImageDestinationCreateWithURL ((__bridge CFURLRef)outURL, (CFStringRef)@"public.png" , 1, NULL);    
    CGImageDestinationAddImage(dr, imageRef, NULL);
    CGImageDestinationFinalize(dr);
}

This code returns the error:

ImageIO: CGImageDestinationAddImage image destination parameter is nil

which I assume means the CGImageDestinationRef is not being created correctly. I haven't been able to find an implementation of this that the new Xcode doesn't give the same error for, what am I doing wrong?

N S
  • 2,524
  • 6
  • 32
  • 42

1 Answers1

4

The code you posted wouldn't work either with or without ARC, because you need to expand the tilde in the path name before passing it.

The code you posted also was leaking the items returned by CGDisplayCreateImage and CGImageDestinationCreateWithURL. Here's an example that works and doesn't leak:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    CGDirectDisplayID displayID = CGMainDisplayID();
    CGImageRef imageRef = CGDisplayCreateImage(displayID); //this is a screenshot (works fine)

    NSString *path = [@"~/Desktop/public.png" stringByExpandingTildeInPath];
    [self savePNGImage:imageRef path:path];

    CFRelease(imageRef);
}

- (void)savePNGImage:(CGImageRef)imageRef path:(NSString *)path
{
    NSURL *fileURL = [NSURL fileURLWithPath:path]; 
    CGImageDestinationRef dr = CGImageDestinationCreateWithURL((__bridge CFURLRef)fileURL, kUTTypePNG , 1, NULL);

    CGImageDestinationAddImage(dr, imageRef, NULL);
    CGImageDestinationFinalize(dr);

    CFRelease(dr);
}
jlehr
  • 15,557
  • 5
  • 43
  • 45
  • 2
    `@"public.png"` is most likely intended as a UTIType, not a filename. However, it's best to use the constant `kUTTypePNG` rather than rolling his own. That said, if it **is** a UTIType, then they'll still need to append a filename as well. – NSGod Nov 22 '11 at 15:59