I am trying to struggle with this issue for two days. I am using Fabric SDK and Rest kit, trying to play with different Rest API web services for Twitter. I can login successfully using TWTRLogInButton
having session object with authTokenSecret
,authToken
and other values. When I try to get user timeline, I always get failure response in return as:
{"errors":[{"code":215,"message":"Bad Authentication data.
"}]}
Full Error log is:
E restkit.network:RKObjectRequestOperation.m:297 Object request failed: Underlying HTTP request operation failed with error: Error Domain=org.restkit.RestKit.ErrorDomain Code=-1011 "Expected status code in (200-299), got 400" UserInfo=0x1780f6f80 {NSLocalizedRecoverySuggestion={"errors":[{"code":215,"message":"Bad Authentication data."}]}, NSErrorFailingURLKey=https://api.twitter.com/1.1/statuses/user_timeline.json?user_id=3116882322&count=2&screen_name=ann_10p, AFNetworkingOperationFailingURLRequestErrorKey=<NSMutableURLRequest: 0x178202740> { URL: https://api.twitter.com/1.1/statuses/user_timeline.json?user_id=3116882322&count=2&screen_name=ann_10p }, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0x1702271e0> { URL: https://api.twitter.com/1.1/statuses/user_timeline.json?user_id=3116882322&count=2&screen_name=ann_10p } { status code: 400, headers {
"Content-Encoding" = gzip;
"Content-Length" = 87;
"Content-Type" = "application/json;charset=utf-8";
Date = "Wed, 01 Apr 2015 09:46:42 GMT";
Server = "tsa_a";
"Strict-Transport-Security" = "max-age=631138519";
"x-connection-hash" = 4c123a59a023cd86b2e9a3e9fc84cd7b;
"x-response-time" = 4;
} }, NSLocalizedDescription=Expected status code in (200-299), got 400}
2015-04-01 14:47:13.223 TwitterIntegration[1086:60b] I restkit.network:RKHTTPRequestOperation.m:154 GET 'https://api.twitter.com/1.1/statuses/user_timeline.json?user_id=3116882322&count=2&screen_name=ann_10p'
2015-04-01 14:47:13.225 TwitterIntegration[1086:60b] E restkit.network:RKHTTPRequestOperation.m:178 GET 'https://api.twitter.com/1.1/statuses/user_timeline.json?user_id=3116882322&count=2&screen_name=ann_10p' (400 Bad Request) [0.0013 s]: Error Domain=org.restkit.RestKit.ErrorDomain Code=-1011 "Expected status code in (200-299), got 400" UserInfo=0x1780f6f80 {NSLocalizedRecoverySuggestion={"errors":[{"code":215,"message":"Bad Authentication data."}]}, NSErrorFailingURLKey=https://api.twitter.com/1.1/statuses/user_timeline.json?user_id=3116882322&count=2&screen_name=ann_10p, AFNetworkingOperationFailingURLRequestErrorKey=<NSMutableURLRequest: 0x178202740> { URL: https://api.twitter.com/1.1/statuses/user_timeline.json?user_id=3116882322&count=2&screen_name=ann_10p }, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0x1702271e0> { URL: https://api.twitter.com/1.1/statuses/user_timeline.json?user_id=3116882322&count=2&screen_name=ann_10p } { status code: 400, headers {
"Content-Encoding" = gzip;
"Content-Length" = 87;
"Content-Type" = "application/json;charset=utf-8";
Date = "Wed, 01 Apr 2015 09:46:42 GMT";
Server = "tsa_a";
"Strict-Transport-Security" = "max-age=631138519";
"x-connection-hash" = 4c123a59a023cd86b2e9a3e9fc84cd7b;
"x-response-time" = 4;
} }, NSLocalizedDescription=Expected status code in (200-299), got 400}
Code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self addLoginButton];
}
-(void) addLoginButton
{
TWTRLogInButton *logInButton = [TWTRLogInButton buttonWithLogInCompletion:^(TWTRSession *session, NSError *error) {
// play with Twitter session
if(session)
{
NSLog(@"logged in success! with session : %@", session);
[Global sharedInstance].session = session;
[self requestUserTimeline];
}
else
{
NSLog(@"session is null");
}
}];
logInButton.center = self.view.center;
[self.view addSubview:logInButton];
}
-(void) requestUserTimeline
{
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[UserTimeline class]];
[mapping addAttributeMappingsFromDictionary:@{
@"text": @"tweetText",
@"favorited": @"favourited",
@"created_at": @"createdAt",
@"user.name": @"name",
@"id": @"tweetID",
@"user.profile_image_url": @"profileImageURL"
}];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); // Anything in 2xx
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:nil keyPath:nil statusCodes:statusCodes];
NSString *params = [NSString stringWithFormat:@"?user_id=3116882322&count=2&screen_name=ann_10p",[Global sharedInstance].session.userID,[Global sharedInstance].session.userName];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[@"https://api.twitter.com/1.1/statuses/user_timeline.json" stringByAppendingString:params]]];
[request setHTTPMethod:@"GET"];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[responseDescriptor]];
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *result) {
UserTimeline *timeline = [result firstObject];
NSLog(@"Mapped the article: %@", timeline);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(@"Failed with error: %@", [error localizedDescription]);
}];
[operation start];
}
Please help me in debugging this problem. Thanks.
All Twitter API access requires a developers account, which can be created quickly by signing up. Essential access will be available immediately, and Elevated access can be requested. Essential: Free, instant access to the Twitter API.
The Twitter API v2 includes a few access levels to help you scale your usage on the platform. In general, new accounts can quickly sign up for free, Essential access. Should you want additional access, you may choose to apply for free Elevated access and beyond.
The Twitter API lets you read and write Twitter data. Thus, you can use it to compose tweets, read profiles, and access your followers' data and a high volume of tweets on particular subjects in specific locations. API stands for Application Programming Interface.
After experimenting with Fabric SDK, I was successful in its integration. I came along with some conclusions, and want to share with you guys.
1) When you first time login the twitter successfully, a session of TWTRSession
has been created for user. It lasts even after you close the app and reopen it.
2) If session has already been created for you, and you try to login getting another session object without logging out, authentication error will be returned.
3) You can check if session exists or not using:
if([[Twitter sharedInstance] session])
{
NSLog(@"session already present!!!");
NSLog(@"signed in as %@", [[[Twitter sharedInstance] session] userName]);
}
else
{
NSLog(@"you need to login!!");
}
4) I will recommend to login using
[[Twitter sharedInstance] logInWithCompletion:^(TWTRSession *session, NSError *error)];
instead of:
[TWTRLogInButton buttonWithLogInCompletion:^(TWTRSession *session, NSError *error)];
Use Twitter's login button only, when you are sure that no session exists currently.
5) If Twitter's authentication is really teasing you up, uninstall the app and try with fresh install. This is last solution!
6) To logout from session, use [[Twitter sharedInstance] logOut];
Coding Part:
I am assuming that you have already followed all the steps by fabric mac app.
First login user, then make timeline request.
-(void) loginUserToTwitter
{
if([[Twitter sharedInstance] session])
{
NSLog(@"session already present!!!");
NSLog(@"signed in as %@", [[[Twitter sharedInstance] session] userName]);
[self getUserTimeline];
}
else
{
NSLog(@"session not found. Make new request!");
[[Twitter sharedInstance] logInWithCompletion:^(TWTRSession *session, NSError *error) {
if(error)
NSLog(@"error occurred... %@",error.localizedDescription);
else
{
NSLog(@"Successfully logged in with session :%@",session);
[self getUserTimeline];
}
}];
}
}
-(void) getUserTimeline
{
NSURLRequest *request = [[[Twitter sharedInstance] APIClient] URLRequestWithMethod:@"GET" URL:@"https://api.twitter.com/1.1/statuses/user_timeline.json"
parameters:@{@"userid": [Twitter sharedInstance].session.userID,
@"count" : @"5",
@"screen_name" : [Twitter sharedInstance].session.userName} error:nil];
NSURLResponse *response;
NSError *error;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if(!data)
{
NSLog(@"error....: %@",error.localizedDescription);
}
else
{
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@",string);
[twitterResponse removeAllObjects];
NSArray *arrayRep = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
twitterResponse = [NSMutableArray arrayWithArray:[TWTRTweet tweetsWithJSONArray:arrayRep]];
[_tableView reloadData];
}
}
I will prefer Twitter SDK's method to extract tweets using [TWTRTweet tweetsWithJSONArray:arrayRep]
instead of Restkit
. Things will be really easy to handle here.
Display Tweets In Twitter's Standard Style:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Setup tableview
self.tableView.estimatedRowHeight = 150;
self.tableView.rowHeight = UITableViewAutomaticDimension; // Explicitly set on iOS 8 if using automatic row height calculation
self.tableView.allowsSelection = NO;
[self.tableView registerClass:[TWTRTweetTableViewCell class] forCellReuseIdentifier:@"TweetCell"];
}
#pragma mark - Tableview Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return twitterResponse.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = @"TweetCell";
TWTRTweetTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
TWTRTweet *tweet = twitterResponse[indexPath.row];
[cell configureWithTweet:tweet];
return cell;
}
// Calculate the height of each row. Must to implement
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
TWTRTweet *tweet = twitterResponse[indexPath.row];
return [TWTRTweetTableViewCell heightForTweet:tweet width:CGRectGetWidth(self.view.bounds)];
}
Note:
Download Fabric SDK from here. You will have to enter email address. They will email you some link for download, you have to follow some steps. Fabric Mac App will have you to completely configure xcode project.
Hope it helps!
References:
Twitter Login
Show Tweets
Cannonball Sample Project
https://github.com/fhsjaagshs/FHSTwitterEngine
try with this FHSTTwitterEngine its working fine
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With