在我的iOS应用中,我想让用户发推文GIF。
我有一个正在运行的TWTRComposer并尝试使用SetImage方法附加GIF:
[composer setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:self.localGifURL]]];
然后图像出现在作曲家视图中,但是当图像发布到Twitter时,它是静态图像而不是GIF。
是否可以将GIF附加到使用TWTRComposer创建的推文上?
修改
我尝试集成这个库来创建一个动画UIImage:
https://github.com/mayoff/uiimage-from-animated-gif
更新我的代码,我有以下内容:
[composer setImage:[UIImage animatedImageWithAnimatedGIFURL:self.localGifURL]];
但这仍然导致Twitter上的静态图像。
编辑#2
另一个观察 - 如果我将GIF保存到手机并尝试直接从照片库(打开看起来像是TWTRComposer窗口)在Twitter上分享它,它会以图像而不是GIF的形式发布。这导致我可能无法将GIF附加到TWTRComposer ......
答案 0 :(得分:3)
我刚刚构建了一个具有GIF功能并且需要能够发布到Twitter的应用程序。不幸的是,他们的作曲家不适用于GIF(我99.9999%肯定,如果你以某种方式让它工作,请告诉我。)
我的解决方案实际上是,如果用户选择在Twitter上分享,将GIF转换为10秒重复播放GIF的视频(我的GIF持续时间为2秒)。
我设法使用AVAssetWriterInput和AVAssetWriterInputPixelBufferAdaptor来完成它。它还给了我一个简单的方式发布到其他社交媒体渠道,因为他们中的许多人不通过作曲家支持GIF(Messenger?)。
以下是在任何可共享平台上分享视频/ GIF /任何其他媒体类型的方法。
确保您的视图控制器响应UIActivityItemSource协议:
source 'https://rubygems.org'
gem 'rails', '3.2.12'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem 'sass-rails', '~> 3.2.3'
gem 'coffee-rails', '~> 3.2.1'
gem 'zurb-foundation'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', :platforms => :ruby
gem 'uglifier', '>= 1.0.3'
end
gem 'jquery-rails', '~> 2.3.0'
group :development do
gem "better_errors"
gem 'annotate'
gem 'pry'
gem 'sqlite3'
end
group :production do
gem 'pg'
end
gem 'ember-rails'
gem 'ember-source', '~> 1.10'
gem 'handlebars-source', '~> 2.0.0'
gem 'active_model_serializers', '~>0.8.0'
gem 'filepicker-rails'
gem 'thin'
gem 'unicorn'
gem 'capistrano'
gem 'simple_form'
# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'
# To use Jbuilder templates for JSON
# gem 'jbuilder'
# Use unicorn as the app server
# gem 'unicorn'
# Deploy with Capistrano
# gem 'capistrano'
# To use debugger
# gem 'debugger'
# File upload extension
gem "paperclip", "~> 4.3"
# Admin
gem 'activeadmin'
然后,我假设您在分享时调用了一些方法:
@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:^{
}];
}
答案 1 :(得分:1)
我刚刚发布了这个问题,但最终还是实现了这个功能。
TWTRComposer仍然不支持添加除图像之外的任何内容,因此我按照建议使用了媒体/上传REST API。我能够推特GIF和视频。在推特任一媒体之前,我创建了一个自定义UIAlertView,让某人编写推文:
然后,当他们点击推文按钮时,如果GIF足够小,就会收到推文。否则,视频会在Twitter上发布。
结果GIF推文:https://twitter.com/spinturntable/status/730609962817294336
结果视频推文:https://twitter.com/spinturntable/status/730609829128081408
以下是我实施此功能的方法(此帖https://stackoverflow.com/a/31259870/1720985提供了大量帮助)。
创建用于撰写推文消息的初始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推文(我添加了一个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);
}
}];
}
}
}
一些额外的事情:当Compose Tweet Alert出现时,我会关注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]];
}
}
希望这对其他人有用,因为我花了很长时间将所有东西拼凑在一起。