将GIF附加到TWTRComposer?

8
在我的iOS应用中,我希望用户能够发布GIF推文。
我有一个可用的TWTRComposer,并尝试使用SetImage方法附加GIF:
[composer setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:self.localGifURL]]];

图像将显示在composer视图中,但是当图像发布到Twitter时,它是一个静态图像而不是GIF。
使用TWTRComposer创建的推文是否可以附加GIF?
编辑
我尝试集成此库以创建动画UIImage:

https://github.com/mayoff/uiimage-from-animated-gif

更新我的代码后,我有以下内容:

[composer setImage:[UIImage animatedImageWithAnimatedGIFURL:self.localGifURL]];

但是这仍然会在Twitter上生成静态图像。 编辑 #2 另一个观察——如果我将GIF保存到手机上并尝试直接从照片库共享到Twitter(打开了一个看起来像TWTRComposer窗口),则发布的是图片而不是GIF。这说明您可能无法将GIF附加到TWTRComposer...
3个回答

3

我认为TWTRComposer目前不支持动态GIF或视频附件。我想你需要直接调用media/upload REST API端点来发布附件,然后使用statuses/update方法将它们附加到一条推文中。


谢谢你的帮助 - 你有没有这样做的例子? - scientiffic
2
@scientiffic 这是使用REST API发布视频的示例。https://dev59.com/EV0Z5IYBdhLWcg3wnBZS - John81
@john81 谢谢你提供这个链接!我猜你需要创建一个自定义窗口,让人们输入他们的推文文本? - scientiffic
@scientiffic 是的,你必须自己创建所有的用户界面。我尝试使用 Twitter 的 SDK Fabric 来完成这个任务,但在 iOS 上它不支持动画 GIF 或视频,只支持图片。 - John81
1
使用REST API的问题在于您会错过一些作曲家提供的好处,例如用户名建议。 - user3344977

3

我刚刚开发了一个具有GIF功能的应用程序,并需要能够发布到Twitter。不幸的是,他们的编辑器无法使用GIF(我99.9999%确定,如果您以某种方式使其工作,请告诉我)。

我的解决方案实际上是,如果用户选择在Twitter上分享,将GIF转换为一个10秒的视频,其中只重复播放GIF(我的GIF始终持续2秒)。

我使用AVAssetWriterInput和AVAssetWriterInputPixelBufferAdaptor成功完成了它。这还为我提供了一种可靠的方法来发布到其他社交媒体平台,因为其中许多平台都不支持通过编辑器发布GIF(Messenger?)。

以下是如何在任何可共享平台上共享视频/GIF/任何其他媒体类型的方法。

确保您的视图控制器响应UIActivityItemSource协议:

@interface MyCustomViewController () <UIActivityItemSource>

那么,我假设您有一些方法可在分享时调用:
- (void)methodCalledToShare {
    //Create an activity view controller
    UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:@[self] applicationActivities:nil];
    //decide what happens after it closes (optional)
    [activityController setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
    }];
    //present the activity view controller
    [self presentViewController:activityController animated:YES completion:^{

    }];
}

那么您需要使用此方法来处理我们之前遵循的协议:

//This is an example for if you want to have different data sent based on which app they choose.
//I have an NSURL pointing to a local video in "videoUrl"
//And I have NSData of a GIF in "gifData"
- (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType {
    id item;
    //If it's Facebook, send a video
    if ([activityType isEqualToString:UIActivityTypePostToFacebook])
        item = self.videoUrl;
    //if its Twitter, send a GIF
    else if ([activityType isEqualToString:UIActivityTypePostToTwitter])
        item = self.gifData;
    //if its mail, send a GIF
    else if ([activityType isEqualToString:UIActivityTypeMail])
        item = self.gifData;
    //If it's text, send a GIF
    else if ([activityType isEqualToString:UIActivityTypeMessage])
        item = self.gifData;
    //If it's Facebook Messenger, send a video
    else if ([activityType isEqualToString:@"com.facebook.Messenger.ShareExtension"])
        item = self.videoUrl;
    //Just default to a video
    else
        item = self.videoUrl;
    return item;
}

哇,谢谢!我会先尝试一下,如果有效的话就会标记答案。 - scientiffic
1
所以我刚刚阅读了你的代码 - 但我仍然不明白你如何使用视频来撰写推文。一旦你有了self.videoURL,你如何使用它分享到Twitter? - scientiffic
共享表单识别到该本地URL上有一个文件,并在其共享中使用该数据。 - AlexKoren
你是否在使用REST API中的media/upload?https://dev.twitter.com/rest/reference/post/media/upload - scientiffic
1
明白了。当你的应用程序扩展并且需要将内容共享到其他平台时,最好只有一个分享按钮,它会弹出UIActivityViewController。这就是它的作用,并符合苹果的设计指南。 - AlexKoren
显示剩余7条评论

1

我之前发布了这个问题,但最终实现了这个功能。

TWTRComposer仍然不支持添加除图像以外的任何内容,因此我使用了建议的media/upload REST API。 我能够发布GIF和视频推文。 在发布媒体之前,我创建了一个自定义的UIAlertView,让用户撰写推文:

enter image description here

当用户点击推文按钮时,如果GIF文件大小足够小,则会发布GIF;否则,将会发布视频。
生成的GIF推文:https://twitter.com/spinturntable/status/730609962817294336 生成的视频推文:https://twitter.com/spinturntable/status/730609829128081408 下面是我实现此功能的方式(非常感谢这篇文章的帮助https://dev59.com/EV0Z5IYBdhLWcg3wnBZS#31259870)。 创建用于撰写推文消息的初始UIAlertView:
-(IBAction)tweet:(id)sender{
    // check if the person has twitter
    if([[Twitter sharedInstance] session]){
        // first, show a pop up window for someone to customize their tweet message, limited to 140 characters
        UIAlertView *tweetAlert = [[UIAlertView alloc] initWithTitle:@"Compose Tweet"
                                                             message:nil
                                                            delegate:self
                                                   cancelButtonTitle:@"Cancel"
                                                   otherButtonTitles:nil];
        tweetAlert.tag = TAG_TWEET;
        tweetTextView = [UITextView new];
        [tweetTextView setBackgroundColor:[UIColor clearColor]];
        CGRect frame = tweetTextView.frame;
        frame.size.height = 500;
        tweetTextView.frame = frame;

        [tweetTextView setFont:[UIFont systemFontOfSize:15]];

        tweetTextView.textContainerInset = UIEdgeInsetsMake(0, 10, 10, 10);

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(limitTextView:) name:@"UITextViewTextDidChangeNotification" object:tweetTextView];


        [tweetTextView setText:[NSString stringWithFormat:@"%@ %@", [[NSUserDefaults standardUserDefaults] valueForKey:@"tweetText"], self.setShareURL]];
        [tweetAlert setValue:tweetTextView forKey:@"accessoryView"];
        [tweetAlert addButtonWithTitle:@"Tweet"];
        [tweetAlert show];
    }else{
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil
                                                        message:@"Please log in with your Twitter account to tweet!"
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
    }

}

然后检测UIAlertView Tweet(我添加了一个UIAlertViewDelegate):

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
   if(alertView.tag == TAG_TWEET){
        if (buttonIndex == 1) {

            UIAlertView *tweetStartAlert = [[UIAlertView alloc] initWithTitle:nil
                                                            message:@"Tweeting..."
                                                           delegate:self
                                                  cancelButtonTitle:nil
                                                  otherButtonTitles:nil];
            [tweetStartAlert show];

            // get client
            __block TWTRAPIClient *client = [[Twitter sharedInstance] APIClient];
            __block NSString *mediaID;

            NSString *text = [tweetTextView text]; // get tweet text
            NSLog(@"text: %@", text);
            NSData *mediaData;
            NSString *mediaLength;
            NSString *mediaType;
            NSString* url = @"https://upload.twitter.com/1.1/media/upload.json";

            // if this is a single spin set, tweet the gif
            if([self.setSpins count] ==1){
                NSLog(@"tweeting GIF with url %@", self.gifURL);
                mediaData = [NSData dataWithContentsOfURL:[NSURL URLWithString:self.gifURL]];
                mediaLength = [NSString stringWithFormat:@"%lu", mediaData.length];
                mediaType = @"image/gif";
            }else if([self.setSpins count] > 1){
                // multi-spin set - tweet the video
                NSLog(@"tweeting video with url %@", self.videoURL);
                mediaData = [NSData dataWithContentsOfURL:[NSURL URLWithString:self.videoURL]];
                mediaLength = [NSString stringWithFormat:@"%lu", mediaData.length];
                mediaType = @"video/mp4";
            }

            NSError *error;
            // First call with command INIT
            __block NSDictionary *message =  @{ @"status":text,
                                                @"command":@"INIT",
                                                @"media_type":mediaType,
                                                @"total_bytes":mediaLength};

                NSURLRequest *preparedRequest = [client URLRequestWithMethod:@"POST" URL:url parameters:message error:&error];
                [client sendTwitterRequest:preparedRequest completion:^(NSURLResponse *urlResponse, NSData *responseData, NSError *error){

                    if(!error){
                        NSError *jsonError;
                        NSDictionary *json = [NSJSONSerialization
                                              JSONObjectWithData:responseData
                                              options:0
                                              error:&jsonError];

                        mediaID = [json objectForKey:@"media_id_string"];
                        NSError *error;

                        NSString *mediaString = [mediaData base64EncodedStringWithOptions:0];

                        // Second call with command APPEND
                        message = @{@"command" : @"APPEND",
                                    @"media_id" : mediaID,
                                    @"segment_index" : @"0",
                                    @"media" : mediaString};

                        NSURLRequest *preparedRequest = [client URLRequestWithMethod:@"POST" URL:url parameters:message error:&error];

                        [client sendTwitterRequest:preparedRequest completion:^(NSURLResponse *urlResponse, NSData *responseData, NSError *error){

                            if(!error){
                                client = [[Twitter sharedInstance] APIClient];
                                NSError *error;
                                // Third call with command FINALIZE
                                message = @{@"command" : @"FINALIZE",
                                            @"media_id" : mediaID};

                                NSURLRequest *preparedRequest = [client URLRequestWithMethod:@"POST" URL:url parameters:message error:&error];

                                [client sendTwitterRequest:preparedRequest completion:^(NSURLResponse *urlResponse, NSData *responseData, NSError *error){

                                    if(!error){
                                        client = [[Twitter sharedInstance] APIClient];
                                        NSError *error;
                                        // publish video with status
                                        NSLog(@"publish video!");
                                        NSString *url = @"https://api.twitter.com/1.1/statuses/update.json";
                                        NSMutableDictionary *message = [[NSMutableDictionary alloc] initWithObjectsAndKeys:text,@"status",@"true",@"wrap_links",mediaID, @"media_ids", nil];
                                        NSURLRequest *preparedRequest = [client URLRequestWithMethod:@"POST" URL:url parameters:message error:&error];

                                        [client sendTwitterRequest:preparedRequest completion:^(NSURLResponse *urlResponse, NSData *responseData, NSError *error){
                                            if(!error){
                                                NSError *jsonError;
                                                NSDictionary *json = [NSJSONSerialization
                                                                      JSONObjectWithData:responseData
                                                                      options:0
                                                                      error:&jsonError];
                                                NSLog(@"%@", json);

                                                [tweetStartAlert dismissWithClickedButtonIndex:0 animated:YES];

                                                UIAlertView *tweetFinishedAlert = [[UIAlertView alloc] initWithTitle:nil
                                                                                                          message:@"Tweeted!"
                                                                                                         delegate:self
                                                                                                cancelButtonTitle:nil
                                                                                                otherButtonTitles:nil];
                                                [tweetFinishedAlert show];
                                                double delayInSeconds = 1.5;
                                                dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
                                                dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
                                                    [tweetFinishedAlert dismissWithClickedButtonIndex:0 animated:YES];
                                                });

                                                [self logShare:@"twitter"];

                                            }else{
                                                NSLog(@"Error: %@", error);
                                            }
                                        }];
                                    }else{
                                        NSLog(@"Error command FINALIZE: %@", error);
                                    }
                                }];

                            }else{
                                NSLog(@"Error command APPEND: %@", error);
                            }
                        }];

                    }else{
                        NSLog(@"Error command INIT: %@", error);
                    }

                }];
            }
        }
    }

一些额外的事情:当“发推文提示框”出现时,我将焦点集中在UITextView上:

- (void)didPresentAlertView:(UIAlertView *)alertView {
    if(alertView.tag == TAG_TWEET){
        NSLog(@"tweetAlertView appeared");
        [tweetTextView becomeFirstResponder];
    }
}

这是我检查UITextView是否少于140个字符的方法:
- (void)limitTextView:(NSNotification *)note {
    int limit = 140;
    if ([[tweetTextView text] length] > limit) {
        [tweetTextView setText:[[tweetTextView text] substringToIndex:limit]];
    }
}

希望这对其他人有用,因为我花了很长时间才把一切东西拼凑在一起。


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