简体   繁体   中英

Access Twitter User Timeline using Fabric SDK iOS

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.

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

You can show a User Timeline directly. No need to handle login or other network calls directly. This will automatically handle Guest Auth , and then loading the initial Tweets as well as loading more when the end of the UITableView is reached:

class UserTimelineViewController: TWTRTimelineViewController, TWTRTweetViewDelegate {

  convenience init() {
    // Set up the User Timeline
    let dataSource = TWTRUserTimelineDataSource(screenName: "TomCruise", APIClient: TWTRAPIClient())

    // Set the data source (will automatically load Tweets in `viewWillAppear`
    self.init(dataSource: dataSource)

    // Update the title displayed in the Navigation bar
    self.title = "@\(dataSource.screenName)"
  }

  func tweetView(tweetView: TWTRTweetView, didSelectTweet tweet: TWTRTweet) {
    // Log a message when a cell is tapped
    print("Selected tweet with ID: \(tweet.tweetID)")
  }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM