2015-04-01 14 views
7

Sto provando a lottare con questo problema per due giorni. Sto usando Fabric SDK e Rest kit, cercando di giocare con diversi servizi web di Rest API per Twitter. Posso accedere correttamente utilizzando TWTRLogInButton con oggetto di sessione con authTokenSecret, authToken e altri valori. Quando cerco di ottenere cronologia utente, ho sempre arrivare risposta di errore in cambio come:Accesso alla cronologia utente di Twitter tramite Fabric SDK iOS

{"errors":[{"code":215,"message":"Bad Authentication data. "}]}

completa log di errore è:

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} 

Codice:

- (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]; 
} 

Per favore aiutatemi nel debug di questo problema Grazie

+0

Dove stai usando il token di autenticazione? – Wain

+0

Come posso usarlo @Wain? Non c'è alcuna documentazione sul passaggio del token di autenticazione in alcuna richiesta. Ma sto ricevendo uno dopo il login. – NightFury

+0

Ci deve essere, perché hai un token e un errore di autenticazione. Anche i token di autenticazione sono standard. Non ho guardato i documenti ma è lì che devi cercare una guida. – Wain

risposta

9

Dopo aver sperimentato con tessuto SDK, ho avuto successo nella sua integrazione. Sono arrivato con alcune conclusioni e voglio condividere con voi ragazzi.

1) La prima volta che si accede correttamente a Twitter, è stata creata una sessione di TWTRSession per l'utente. Dura anche dopo aver chiuso l'app e riaprirla.

2) Se la sessione è già stata creata per te e si tenta di accedere a ottenere un altro oggetto di sessione senza disconnettere, verrà restituito l'errore di autenticazione.

3) È possibile controllare se la sessione esiste o non utilizzo:

if([[Twitter sharedInstance] session]) 
{ 
    NSLog(@"session already present!!!"); 
    NSLog(@"signed in as %@", [[[Twitter sharedInstance] session] userName]); 
} 
else 
{ 
NSLog(@"you need to login!!"); 
} 

4) mi consiglia di effettuare il login utilizzando

[[Twitter sharedInstance] logInWithCompletion:^(TWTRSession *session, NSError *error)];

invece di:

[TWTRLogInButton buttonWithLogInCompletion:^(TWTRSession *session, NSError *error)];

Utilizzare solo il pulsante di accesso di Twitter, quando si è sicuri che non esiste alcuna sessione attualmente.

5) Se l'autenticazione di Twitter ti sta davvero prendendo in giro, disinstalla l'app e prova con una nuova installazione. Questa è l'ultima soluzione!

6) Per disconnettersi dalla sessione, utilizzare [[Twitter sharedInstance] logOut];

parte di codifica:

Io parto dal presupposto che avete già seguito tutti i passaggi da Mac App tessuto.

Primo accesso utente, quindi effettuare la richiesta della sequenza temporale.

-(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]; 
    } 
} 

Io preferisco il metodo di Twitter SDK per estrarre i tweet utilizzando [TWTRTweet tweetsWithJSONArray:arrayRep] invece di Restkit. Le cose saranno veramente facili da gestire qui.

Mostra tweet in stile standard di Twitter:

- (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)]; 

} 

Nota:

Scarica tessuto SDK da here. Dovrai inserire l'indirizzo email. Ti invieranno un'email di collegamento per il download, dovrai seguire alcuni passaggi. Fabric Mac App ti permetterà di configurare completamente il progetto xcode.

Spero che aiuti!

Riferimenti:

Twitter Login

Show Tweets

Cannonball Sample Project

+0

Grazie mille la tua risposta è fantastica. – Mariam

+0

Contento di poter aiutare :) – NightFury

+0

Ho provato questo e ho ottenuto l'applicazione di chiusura a causa di eccezione non rilevata 'NSInvalidArgumentException', motivo: '*** - [__NSPlaceholderDictionary initWithObjects: forKeys: count:]: tentativo di inserire nil oggetto da oggetti [0 ] ' – user717452

0

È possibile visualizzare una linea temporale utente direttamente. Non è necessario gestire direttamente il login o altre chiamate di rete. Questo gestirà automaticamente Guest Auth, e poi caricare i Tweets iniziali così come il caricamento di più quando viene raggiunta la fine del UITableView:

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)") 
    } 

} 
Problemi correlati