I am trying to integrate Twitter in my iOS application.
The application is expected to support iOS versions 6.x & 7.x.
I want to directly post a tweet once the user taps on a button in my UI, without again asking confirmation in SLComposeViewController alert.
I have gone through the following posts which say how to do that, problem being that they are both configured for iOS 5.x.
Stack Overflow Link 1
Stack Overflow Link 2
How exactly do I go about it?
Any help will be appreciated.
I see no differences from iOS 5.1 to iOS 6.0, neither iOS 6.1 to 7.0 for Twitter api.
Use the iOS 5 tutorials and check with alt+left mouse click to inform about deprications or modified functions if there are.
Maybe this will help.
In the two links you mentioned they are using Twitter Api v1. which is deprecated a long time ago: API V1 no longer function instead you should be using the V1.1 so the url to post a tweet will be https://api.twitter.com/1.1/statuses/update.json
In addition TWRequest is also deprecated in iOS 6.0 you should use SLRequest
Here is a simple code to do so:
- (void) sendTweetWithoutPromp:(NSString*) tweetText
{
NSString *url = #"https://api.twitter.com/1.1/statuses/update.json";
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0];
[params setObject:tweetText forKey:#"status"];
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error) {
if(granted)
{
NSArray *accountsArray = [accountStore accountsWithAccountType:accountType];
if ([accountsArray count] > 0)
{
ACAccount *twitterAccount = [accountsArray objectAtIndex:0];
SLRequest *postRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:TWRequestMethodPOST URL:[NSURL URLWithString:url] parameters:params ];
[postRequest setAccount:twitterAccount];
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
NSString *output = [NSString stringWithFormat:#"HTTP response status: %i", [urlResponse statusCode]];
NSLog(#"output = %#",output);
dispatch_async( dispatch_get_main_queue(), ^{
if (error)
{
}
});
}];
}
else
{
NSLog(#"no Account in Settings");
}
}
}];
}
Related
As a part of my project I need to show the list of tweets in iOS app. I tried with the below code but its returning the JSON. The same code is works fine with version 1. Now the twitter api version is 1.1 and one another warning I got that TWRequest is deprecated. This deprecation is not the issue of this even I got same thing with SLRequest. Here my problem is I need to fetch the JSON of Particular user tweets without authentication or with authentication
TWRequest *postequest=[[TWRequest alloc]initWithURL:[NSURL URLWithString:#"https://api.twitter.com/1.0/statuses/user_timeline.json?screen_name=coolCracker&count=2"] parameters:nil requestMethod:TWRequestMethodGET];
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
NSString *output;
if ([urlResponse statusCode]==200) {
NSError *err;
NSDictionary *PublicTimeline=[NSJSONSerialization JSONObjectWithData:responseData options:0 error:&err];
output=[NSString stringWithFormat:#"HTTP response status: %li\nPublic timeline:\n%#",(long)[urlResponse statusCode],PublicTimeline];
}
else
{
output=[NSString stringWithFormat:#"No feed HTTP response was: %li\n",(long)[urlResponse statusCode]];
}
[self performSelectorOnMainThread:#selector(displayResults:) withObject:output waitUntilDone:NO];
}];
-(void)displayResults:(NSString *)text
{
NSLog(#"tweets feed %#",text);
}
I used this in my work and it worked pretty well. Use STTwitter. Download STTwitter files here.
Place this in your view didload:
STTwitterAPI *twitter = [STTwitterAPI twitterAPIAppOnlyWithConsumerKey:#"your consumer key"
consumerSecret:#"your secret key"];
[twitter verifyCredentialsWithSuccessBlock:^(NSString *bearerToken) {
[twitter getUserTimelineWithScreenName:#"your twitter account name"
successBlock:^(NSArray *statuses) {
self.twitterFeedList = [NSMutableArray arrayWithArray:statuses];
[self->listView reloadData];
} errorBlock:^(NSError *error) {
NSLog(#"%#", error.debugDescription);
}];
} errorBlock:^(NSError *error) {
NSLog(#"%#", error.debugDescription);
}];
Hi Below code is working for me. Though TWRequest is deprecated it works for now. Later you can change it to SLRequest.
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *twitterType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
// Request access from the user to use their Twitter accounts.
[accountStore requestAccessToAccountsWithType:twitterType options:nil completion:^(BOOL granted, NSError *error) {
if (granted == YES){
//get accounts to use.
NSArray *accounts = [accountStore accountsWithAccountType:twitterType];
if ([accounts count] > 0) {
NSLog(#"account: %#", accounts);
ACAccount *loggedinaccount;
loggedinaccount = accounts[0];
// get tweets
TWRequest *postRequest=[[TWRequest alloc]initWithURL:[NSURL URLWithString:#"https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=HuntEthane&count=2"] parameters:nil requestMethod:TWRequestMethodGET];
[postRequest setAccount:loggedinaccount];
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
NSString *output;
if ([urlResponse statusCode]==200) {
NSError *err;
NSDictionary *PublicTimeline=[NSJSONSerialization JSONObjectWithData:responseData options:0 error:&err];
output=[NSString stringWithFormat:#"HTTP response status: %li\nPublic timeline:\n%#",(long)[urlResponse statusCode],PublicTimeline];
}
else
{
output=[NSString stringWithFormat:#"No feed HTTP response was: %li\n",(long)[urlResponse statusCode]];
}
[self performSelectorOnMainThread:#selector(displayResults:) withObject:output waitUntilDone:NO];
}];
}
}else{
// show alert to inser user_name and password to login on twitter
UIAlertView *alertTwitterAccount = [[UIAlertView alloc]
initWithTitle:#"Enter with your twitter account"
message:nil
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Login", nil];
[alertTwitterAccount setAlertViewStyle:UIAlertViewStyleLoginAndPasswordInput];
[[alertTwitterAccount textFieldAtIndex:0] setPlaceholder:#"User"];
[alertTwitterAccount setDelegate:self];
[alertTwitterAccount setTag:1];
[alertTwitterAccount show];
}
}];
Remember to add below frameworks to make this code work.
Twitter.FrameWork
Social.FrameWork
Accounts.Framework
Security.FrameWork
If you want to use SLRequest instead of TWRequest, replace request statement with below statement
SLRequest *postRequest = [SLRequest
requestForServiceType:SLServiceTypeTwitter
requestMethod:SLRequestMethodGET
URL:[NSURL URLWithString:#"https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=HuntEthane&count=2"]parameters:nil];
Moving forward the easiest way is adoption of Fabric.io from Tweeter as the development platform includes Tweeter embeds: https://get.fabric.io/native-social
"The easiest way to bring Twitter content into your app."
Honestly, I did not look into authentication part needed for Fabric.io.
Otherwise you need to follow and respect rules for accessing Twitter REST APIs or Streaming APIs, both well documented. OAuth authentication is required.
If you wish to avoid authentication in your app you can write a simple web REST API that will take care of authentication and serve (selected) tweets to your iOS app.
First, you’ll need to register an app with Twitter
Write down your Consumer Key and Consumer Secret
Write a simple server API (proxy) in your language of choice.
I personally prefer JavaScript on Node.js. Consider using libraries like express.js and oauth available on npm, but you can search npm for any other implemented Twitter proxy/API.
The code essentially consists of getting an OAuth Access token and then calling selected twitter APIs, and respecting ratelimits by caching results.
I know there is lots of things given about twitter integration and private tweets.
But I want to know that if I use TWRequest in ios7 then it will work or not?
My code snippet as follows.
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error){
if(granted)
{
// Get the list of Twitter accounts.
NSArray *accountsArray = [accountStore accountsWithAccountType:accountType];
// For the sake of brevity, we'll assume there is only one Twitter account present.
// You would ideally ask the user which account they want to tweet from, if there is more than one Twitter account present.
if ([accountsArray count] > 0) {
// Grab the initial Twitter account to tweet from.
ACAccount *twitterAccount = [accountsArray objectAtIndex:0];
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init];
[tempDict setValue:#"rohit40793982" forKey:#"screen_name"];
//[tempDict setValue:#"true" forKey:#"follow"];
// [tempDict setValue:#"683286" forKey:#"user_id "];
TWRequest *postRequest = [[TWRequest alloc] initWithURL:[NSURL URLWithString:#"https://twitter.com/snehalikanksha/status/388535072359317504.json"]
parameters:tempDict
requestMethod:TWRequestMethodPOST];
[postRequest setAccount:twitterAccount];
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
NSLog(#"%#",urlResponse);
NSArray *tweets = [NSJSONSerialization JSONObjectWithData:responseData
options:kNilOptions
error:&error];
NSLog(#"%#",tweets);
NSString *output = [NSString stringWithFormat:#"HTTP response status: %i", [urlResponse statusCode]];
NSLog(#"%#", output);
[self performSelectorOnMainThread:#selector(displayText) withObject:output waitUntilDone:NO];
}];
}
}
}];
Can anybody help me ?
It gives Http error 403.
and log shows
"Your account may not be allowed to perform this action. Please <a class=\"js-reload\" href=\"#\">refresh the page</a> and try again."
I'm not sure of what you're trying to do but the reason why your code doesn't work is that you're not using a Twitter API endpoint.
If you want to get details for a specific tweet, you can use GET statuses/show/:id.
You would have to change your code for:
NSURL *url = [NSURL URLWithString:#"https://api.twitter.com/1.1/statuses/show.json?id=388535072359317504"];
TWRequest *request = [[TWRequest alloc] initWithURL:url
parameters:nil
requestMethod:TWRequestMethodGET];
The STTwitter library can help you in using the API by mapping every endpoint to an Objective-C method.
I have created a Facebook app for my iOS application in Facebook developer console, but when I use that app id, even though I get the response as success it won't get posted. Please find below my code.(even I get the id for that particular post)
But the point is when I execute same code with my existing Facebook app id(Which is currently using for my live app), this get posted and works fine, so my assumption is, there is something I have to do in Facebook app configuration in the developer console, but I couldn't find. can anyone give me a clue?
Thanks in advance.
Note : I use iOS 6 social framwork
Get User method
- (void)getUserAndShare {
NSLog(#"Getting User");
if(!_accountStore)
_accountStore = [[ACAccountStore alloc] init];
ACAccountType *facebookTypeAccount = [_accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
[_accountStore requestAccessToAccountsWithType:facebookTypeAccount
options:#{ACFacebookAppIdKey: #"xxxxxxxxxxxxxx", ACFacebookPermissionsKey: #[#"email"]}
completion:^(BOOL granted, NSError *error) {
if(granted){
NSArray *accounts = [_accountStore accountsWithAccountType:facebookTypeAccount];
_facebookAccount = [accounts lastObject];
NSLog(#"Success account");
[_accountStore renewCredentialsForAccount:_facebookAccount completion:^(ACAccountCredentialRenewResult renewResult, NSError *error) {
if (error){
}
[self postPhoto:nil];
}];
}
}];
}
Share method
-(IBAction)postPhoto{
if(!_accountStore)
_accountStore = [[ACAccountStore alloc] init];
NSDictionary *parameters = #{#"message": #"this is a resource picture 2", ACFacebookAppIdKey: #"xxxxxxxxxxxxxx"};
SLRequest *facebookRequest = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodPOST
URL:[NSURL URLWithString:#"https://graph.facebook.com/me/photos"]
parameters:parameters];
NSData *data = UIImagePNGRepresentation([UIImage imageNamed:#"sec.jpg"]);
[facebookRequest addMultipartData: data
withName:#"source"
type:#"multipart/form-data"
filename:#"msg.jpg"];
facebookRequest.account = _facebookAccount;
[facebookRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error)
{
if (error) {
}
else
{
NSLog(#"Post successful");
NSString *dataString = [[NSString alloc] initWithData:responseData encoding:NSStringEncodingConversionAllowLossy];
NSLog(#"Response Data: %#", dataString);
}
}];
}
Edit : Is it required to request special permission to use graph API when calling requestAccessToAccountsWithType ?
Finally i got it working, and my assumption was correct :) I have to add new permission when i requesting the access. So as i said it worked in my previous Facebook app ID, thats because i have already granted the permission for that app. Anyway, for those who interest to see what is the solution, find it below,
//Specify App ID and permissions
NSDictionary *options = #{
ACFacebookAppIdKey: #"xxxxxxxxxxxxxxx",
ACFacebookPermissionsKey: #[#"publish_stream", #"publish_actions"],
ACFacebookAudienceKey: ACFacebookAudienceFriends
};
Requested two new permissions publish_stream and publish_actions
I think the issue is with your MIME type, issue in this line:
[facebookRequest addMultipartData: data
withName:#"source"
type:#"multipart/form-data"
filename:#"msg.jpg"];
Change that to:
[facebookRequest addMultipartData:data
withName:#"media"
type:#"image/jpeg"
filename:#"msg.jpg"];
I'm developing a Twitter Feed View for an iOS App. I found TWRequest and it works exactly like that which i was looking for. But: i get an Notice: "TWRequest is deprecated: first deprecated in iOS 6.0". What should I use instead?
On iOS 6 you should use the Social.framework. This has a class named SLRequest.
You use it almost in the same way as the deprecated TWRequest, but you need to specify that it's a twitter request as opposed to a facebook request.
The entire Twitter.framework became deprecated as of iOS 6, since Apple added Facebook and Weibo (a Chinese social network) to iOS 6, they grouped all social classes into the new Social.framework.
Note you must specify the service type for Twitter/Facebook, Example:
SLRequest *aRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter
requestMethod:SLRequestMethodPOST
URL:myurl
parameters:myparams];
Be sure to check out the documentation.
Here is a complete code to upload text + image to your Twitter Account using Twitter api
UIImage *img = [UIImage imageNamed:#"twitterImage.png"];
ACAccountStore *account = [[ACAccountStore alloc] init];
ACAccountType *accountType = [account accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[account requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) {
if (granted == YES) {
// Populate array with all available Twitter accounts
NSArray *arrayOfAccounts = [account accountsWithAccountType:accountType];
if ([arrayOfAccounts count] > 0) {
ACAccount *acct = [arrayOfAccounts objectAtIndex:0];
NSDictionary *message = #{#"status": #"From my app"};
NSURL *requestURL = [NSURL URLWithString:#"https://upload.twitter.com/1/statuses/update_with_media.json"];
SLRequest *postRequest = [SLRequest
requestForServiceType:SLServiceTypeTwitter
requestMethod:SLRequestMethodPOST
URL:requestURL parameters:message];
NSData *data = UIImagePNGRepresentation(img);
[postRequest addMultipartData:data withName:#"media" type:#"image/png" filename:#"TestImage"];
postRequest.account = acct;
[postRequest performRequestWithHandler:
^(NSData *responseData, NSHTTPURLResponse
*urlResponse, NSError *error)
{
if (error) {
NSLog(#"%#",error.description);
}
else {
NSLog(#"Upload Sucess !");
}
}];
}
}
}];
In case you plan on integrating TwitterKit by Twitter to perform the tweets via your custom twitter app then this might help you.
https://stackoverflow.com/a/28602749/1740354
Another alternative is to use Twitter API. You should have Twitter framework for that.
Then do following code:
NSString *statusesShowEndpoint = #"https://api.twitter.com/1.1/statuses/update.json";
NSDictionary *params = #{#"status": #"Hello, my first autopost tweet..."};
NSError *clientError;
NSURLRequest *request = [[[Twitter sharedInstance] APIClient]
URLRequestWithMethod:#"POST"
URL:statusesShowEndpoint
parameters:params
error:&clientError];
if (request) {
[[[Twitter sharedInstance] APIClient]
sendTwitterRequest:request
completion:^(NSURLResponse *response,
NSData *data,
NSError *connectionError) {
if (data) {
// handle the response data e.g.
NSError *jsonError;
NSDictionary *dicResponse = [NSJSONSerialization
JSONObjectWithData:data
options:0
error:&jsonError];
NSLog(#"%#",[dicResponse description]);
}
else {
NSLog(#"Error code: %ld | Error description: %#", (long)[connectionError code], [connectionError localizedDescription]);
}
}];
}
else {
NSLog(#"Error: %#", clientError);
}
Essentially what I want is for the app, once the user has allowed access to their Twitter account, to be able to tweet whatever the user has selected in a UITableView. Ideally I'd like to use the Twitter framework in iOS 5, but the main issue I'm having is the modal view controller for tweeting. Is this optional? Is it possible to tweet without it and if not, what do you suggest I do?
Thanks!
It's definitely possible to tweet without it, the following is in production iOS 5 apps. It even takes the user to the requisite section of preferences if they haven't registered an account.
- (void)postToTwitter
{
// Create an account store object.
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
// Create an account type that ensures Twitter accounts are retrieved.
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
// Request access from the user to use their Twitter accounts.
[accountStore requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) {
if(granted) {
// Get the list of Twitter accounts.
NSArray *accountsArray = [accountStore accountsWithAccountType:accountType];
if ([accountsArray count] > 0) {
// Grab the initial Twitter account to tweet from.
ACAccount *twitterAccount = [accountsArray objectAtIndex:0];
TWRequest *postRequest = nil;
postRequest = [[TWRequest alloc] initWithURL:[NSURL URLWithString:#"http://api.twitter.com/1/statuses/update.json"] parameters:[NSDictionary dictionaryWithObject:[self stringToPost] forKey:#"status"] requestMethod:TWRequestMethodPOST];
// Set the account used to post the tweet.
[postRequest setAccount:twitterAccount];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^(void) {
if ([urlResponse statusCode] == 200) {
Alert(0, nil, #"Tweet Successful", #"Ok", nil);
}else {
Alert(0, nil, #"Tweet failed", #"Ok", nil);
}
});
}];
});
}
else
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"prefs:root=TWITTER"]];
}
}
}];
}
This would be an updated version using SLRequest instead of TWRequest, which was deprecated in iOS 6.
Note this needs the Social and Accounts framework to be added to your project...
- (void) postToTwitterInBackground {
// Create an account store object.
ACAccountStore *accountStore = [[ACAccountStore alloc] init];
// Create an account type that ensures Twitter accounts are retrieved.
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
// Request access from the user to use their Twitter accounts.
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error) {
if(granted) {
// Get the list of Twitter accounts.
NSArray *accountsArray = [accountStore accountsWithAccountType:accountType];
if ([accountsArray count] > 0) {
// Grab the initial Twitter account to tweet from.
ACAccount *twitterAccount = [accountsArray objectAtIndex:0];
SLRequest *postRequest = nil;
// Post Text
NSDictionary *message = #{#"status": #"Tweeting from my iOS app!"};
// URL
NSURL *requestURL = [NSURL URLWithString:#"https://api.twitter.com/1.1/statuses/update.json"];
// Request
postRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodPOST URL:requestURL parameters:message];
// Set Account
postRequest.account = twitterAccount;
// Post
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
NSLog(#"Twitter HTTP response: %i", [urlResponse statusCode]);
}];
}
}
}];
}
Update: The TwitterKit in Fabric by Twitter is quite handy and if you aim to post from your Twitter app when the user tries to Tweet in your app then it might be a good option to consider.
(YES, this method will allow you to post to twitter without any dialog box or confirmation).
The TwitterKit will handle the permissions part and using the TWTRAPIClient we perform the tweet through the Twitter rest APIs.
//Needs to performed once in order to get permissions from the user to post via your twitter app.
[[Twitter sharedInstance]logInWithCompletion:^(TWTRSession *session, NSError *error) {
//Session details can be obtained here
//Get an instance of the TWTRAPIClient from the Twitter shared instance. (This is created using the credentials which was used to initialize twitter, the first time)
TWTRAPIClient *client = [[Twitter sharedInstance]APIClient];
//Build the request that you want to launch using the API and the text to be tweeted.
NSURLRequest *tweetRequest = [client URLRequestWithMethod:#"POST" URL:#"https://api.twitter.com/1.1/statuses/update.json" parameters:[NSDictionary dictionaryWithObjectsAndKeys:#"TEXT TO BE TWEETED", #"status", nil] error:&error];
//Perform this whenever you need to perform the tweet (REST API call)
[client sendTwitterRequest:tweetRequest completion:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
//Check for the response and update UI according if necessary.
}];
}];
Hope this helps.
The accepted answer is no longer valid due to several changes. This one works with iOS 10, Swift 3, and version 1.1 of Twitter's API.
** UPDATE **
This answer has been updated as the previous one relied upon a deprecated Twitter endpoint.
import Social
import Accounts
func postToTwitter() {
let accountStore = ACAccountStore()
let accountType = accountStore.accountType(withAccountTypeIdentifier: ACAccountTypeIdentifierTwitter)
accountStore.requestAccessToAccounts(with: accountType, options: nil) { (granted, error) in
if granted, let accounts = accountStore.accounts(with: accountType) {
// This will default to the first account if they have more than one
if let account = accounts.first as? ACAccount {
let requestURL = URL(string: "https://api.twitter.com/1.1/statuses/update.json")
let parameters = ["status" : "Tweet tweet"]
guard let request = SLRequest(forServiceType: SLServiceTypeTwitter, requestMethod: .POST, url: requestURL, parameters: parameters) else { return }
request.account = account
request.perform(handler: { (data, response, error) in
// Check to see if tweet was successful
})
} else {
// User does not have an available Twitter account
}
}
}
}
This is the API that is being used.