Доступ к пользовательской временной шкале Twitter с использованием Fabric SDK iOS
Я пытаюсь бороться с этим вопросом в течение двух дней. Я использую Fabric SDK и набор Rest, пытаясь поиграть с различными веб-сервисами Rest API для Twitter. Я могу успешно войти, используя TWTRLogInButton
имеющий объект сеанса с authTokenSecret
,authToken
и другие ценности. Когда я пытаюсь получить временную шкалу пользователя, я всегда получаю ответ об ошибке в виде:
{"errors":[{"code":215,"message":"Bad Authentication data.
"}]}
Полный журнал ошибок:
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}
Код:
- (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];
}
Пожалуйста, помогите мне в устранении этой проблемы. Благодарю.
3 ответа
После экспериментов с Fabric SDK мне удалось успешно его интегрировать. Я пришел с некоторыми выводами и хочу поделиться с вами, ребята.
1) При первом успешном входе в твиттер сеанс TWTRSession
был создан для пользователя. Это продолжается даже после того, как вы закроете приложение и снова откроете его.
2) Если сессия уже была создана для вас, и вы пытаетесь войти в систему, получая другой объект сеанса без выхода из системы, будет возвращена ошибка аутентификации.
3) Вы можете проверить, существует ли сессия или нет:
if([[Twitter sharedInstance] session])
{
NSLog(@"session already present!!!");
NSLog(@"signed in as %@", [[[Twitter sharedInstance] session] userName]);
}
else
{
NSLog(@"you need to login!!");
}
4) Я буду рекомендовать войти используя
[[Twitter sharedInstance] logInWithCompletion:^(TWTRSession *session, NSError *error)];
вместо:
[TWTRLogInButton buttonWithLogInCompletion:^(TWTRSession *session, NSError *error)];
Используйте кнопку входа в Twitter только тогда, когда вы уверены, что в данный момент не существует ни одного сеанса
5) Если аутентификация Twitter действительно вас дразнит, удалите приложение и попробуйте с новой установкой. Это последнее решение!
6) Чтобы выйти из сеанса, используйте [[Twitter sharedInstance] logOut];
Часть кодирования:
Я предполагаю, что вы уже выполнили все шаги с помощью приложения Fabric Mac.
Сначала войдите в систему, затем сделайте запрос временной шкалы.
-(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];
}
}
Я предпочитаю метод Twitter SDK для извлечения твитов, используя [TWTRTweet tweetsWithJSONArray:arrayRep]
вместо Restkit
, С вещами здесь будет действительно легко справиться.
Отображать твиты в стандартном стиле 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)];
}
Замечания:
Загрузите Fabric SDK отсюда. Вам нужно будет ввести адрес электронной почты. Они отправят вам по электронной почте ссылку для скачивания, вам нужно выполнить несколько шагов. Приложение Fabric Mac позволит вам полностью настроить проект xcode.
Надеюсь, поможет!
Рекомендации:
https://github.com/fhsjaagshs/FHSTwitterEngine
попробуйте с этим FHSTTwitterEngine его работает нормально
Вы можете показать пользовательскую временную шкалу напрямую. Нет необходимости обрабатывать логин или другие сетевые вызовы напрямую. Это будет автоматически обрабатывать Guest Auth
, а затем загружать начальные твиты, а также загружать больше, когда конец 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)")
}
}