Reputation: 11787
I'm pretty new to Objective-C, but have been mostly understanding everything so far. I am stuck, however, on trying to share an animated GIF through NSSharingService
.
I am attaching the image like so, where image
is a string containing the URL of an animated GIF (https://i.sstatic.net/yMmpI.gif for example):
NSImage *imageData = [[NSImage alloc] initWithContentsOfURL:[NSURL URLWithString:image]];
NSArray *shareItems = [NSArray arrayWithObjects:imageData, href, nil];
NSSharingService *service = [NSSharingService sharingServiceNamed:NSSharingServiceNameComposeMessage];
service.delegate = self;
[service performWithItems:shareItems];
When the code is run and the message is sent, however, the image gets sent as a PNG file instead of a GIF.
My suspicion is that the image is either being flattened by NSImage
or NSData
, and that I need to first save the image to the disk and then attempt to send it. I am wondering, though, if this can be accomplished without that extra step of saving.
Edit 1:
I found a GitHub repo which was attempting to answer a similar problem. A solution was never found, however, but the last bit of advice was:
However, when I add an
NSAttributedString
with a GIF attachment toNSSharingServicePicker
, the shared image is not animated. I can't add the wrapperRTFD
data to the picker, as it can only share objects that supportNSPasteboardWriting
protocol, and theRTFD
is returned asNSData
.Copying
RTFD
data to pasteboard asNSRTFDPboardType
works and preserves animation
Would it be possible to convert the GIF to an RTDF
object, copy it to the pasteboard, retrieve the pasteboard item, then share that object? Or is it impossible to preserve animation with NSSharingService
?
Edit 2:
As @Cocoadelica mentioned in the comments, I'm wondering if CoreImage
might be required to preserve animation. I attempted saving the GIF file to the hard drive first, then loading it into NSImage
, but it once again converted it into a static PNG.
This is very, very, very frustrating.
Upvotes: 4
Views: 948
Reputation: 11787
I ended up getting a response via the Cocoa-dev mailing list. Basically, you need to attach an NSURL
directly linking to the file. It doesn't work for external images, and NSImage
is never used:
NSString *fileUrl = @"http://i.imgur.com/V8w9fKt.gif";
NSString *fileName = [fileUrl lastPathComponent];
NSURL *saveUrl = [NSURL URLWithString:[NSString stringWithFormat:@"file://%@", NSTemporaryDirectory()]];
saveUrl = [saveUrl URLByAppendingPathComponent:fileName];
// Write image to temporary directory
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileUrl]];
[data writeToURL:saveUrl atomically:YES];
// Attach the raw NSURL pointing to the local file
NSArray *shareItems = [NSArray arrayWithObjects:saveUrl, @"Text", nil];
// Open share prompt
NSSharingService *service = [NSSharingService sharingServiceNamed:NSSharingServiceNameComposeMessage];
service.delegate = self;
[service performWithItems:shareItems];
I then implemented didShareItems and didFailToShareItems so that I could remove the file after sharing was complete:
- (void)sharingService:(NSSharingService *)sharingService didShareItems:(NSArray *)items{
NSString *path = items[0];
[self removeFile:path];
}
...
- (void)removeFile:(NSString *)path{
[[NSFileManager defaultManager] removeItemAtPath:path error:NULL];
}
And for those struggling, I found the following method was required for everything to work properly:
- (NSWindow *)sharingService:(NSSharingService *)sharingService sourceWindowForShareItems:(NSArray *)items sharingContentScope:(NSSharingContentScope *)sharingContentScope{
return self.window;
}
I realize some of that code is improper (my URLWithString
creation is counterintuitive, but I'm learning), but this should get those struggling a starting point.
Upvotes: 2