NSSharingService可以分享动态GIF吗?

4

我对Objective-C还比较陌生,但目前为止大部分都能理解。不过我卡在了尝试通过NSSharingService分享动态GIF图像上。

我使用以下方式添加图像,其中image是包含动态GIF图像的URL的字符串(例如http://i.imgur.com/V8w9fKt.gif):

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];
当代码运行并发送消息时,图片以PNG文件的形式发送,而不是GIF。

我怀疑图片可能被NSImageNSData压缩了,我需要先将图片保存到磁盘上,然后再尝试发送。但我想知道是否可以在不进行额外保存步骤的情况下完成此操作。

编辑1:

我发现一个GitHub repo,它试图解决类似的问题。然而,从未找到解决方案,但最后一条建议是:

然而,当我将带有GIF附件的NSAttributedString添加到NSSharingServicePicker中时,共享的图像不会动画。 我无法将包装器RTFD数据添加到选择器中,因为它只能共享支持NSPasteboardWriting协议的对象,而RTFD返回为NSData。将RTFD数据复制到剪贴板作为NSRTFDPboardType有效,并保留动画 是否可能将GIF转换为RTDF对象,将其复制到剪贴板,检索粘贴板项,然后共享该对象?或者使用NSSharingService无法保留动画? 编辑2:正如@Cocoadelica在评论中提到的那样,我想知道是否需要CoreImage来保留动画。 我尝试先将GIF文件保存到硬盘上,然后加载到NSImage中,但它再次将其转换为静态PNG。

这真的非常、非常、非常令人沮丧。


我只熟悉iOS和GIF处理,但很可能是NSImage在处理。NSData不关心类型,它只接收字节。你可能需要降到CoreImage来保持GIF格式并通过它获取数据。 - Cocoadelica
@Cocoadelica 那么在 NSImage 中保留类型没有直接的方法吗?我还没有处理过 CoreImage,所以我不太确定我应该用它做什么。 - Charlie
就像我说的,我更熟悉UImage,但本质上它是一个图像数据的容器,您可以从中生成不同格式的图像表示。它没有单一的“类型”。当您处理CoreImage时,它是基于C的API,并且您正在处理源文件中的图像文件,因此gif就是gif。甚至还有一些工具可以从单个帧制作gif,这些帧可以是UI/NSImages。 - Cocoadelica
我曾经处理过动态GIF图像,虽然在Cocoa中可以接收、处理和存储它们,但是真正查看它们的唯一方法是在Web视图中,标准的图像视图对象不支持GIF动画。如果是静态GIF,则事情会更容易,只需记住您的NSImage是围绕可以输出任何内容的图像数据的包装器即可。 - Cocoadelica
@Cocoadelica,其实我甚至不需要显示它,只需将原始gif附加到NSSharingService中发送即可。我不确定能否通过NSSharingService发送核心动画数据。 - Charlie
1个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
2

我最终通过Cocoa-dev邮件列表得到了回复。基本上,您需要附加一个直接链接到文件的NSURL。它不适用于外部图像,并且NSImage从未被使用:

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];
我随后实现了didShareItems和didFailToShareItems方法,以便在分享完成后删除文件:
- (void)sharingService:(NSSharingService *)sharingService didShareItems:(NSArray *)items{
    NSString *path = items[0];
    [self removeFile:path];
}

...

- (void)removeFile:(NSString *)path{
    [[NSFileManager defaultManager] removeItemAtPath:path error:NULL];
}

对于那些遇到困难的人,我发现以下方法是必需的,以使一切正常工作:

- (NSWindow *)sharingService:(NSSharingService *)sharingService sourceWindowForShareItems:(NSArray *)items sharingContentScope:(NSSharingContentScope *)sharingContentScope{
    return self.window;
}

我意识到部分代码不太规范(我的URLWithString创建方式有些反直觉,但我正在学习),但这应该能为那些刚开始学习的人提供一个起点。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,