2

アプリを Twitter API 1.1 で更新する必要があります。以前は、次の URL を使用してツイートを取得しました。

http://search.twitter.com/search.json?tag=ios&rpp=25

しかし、今はうまくいきません。Twitter APIドキュメントから次のURLを使用しようとしました:

https://api.twitter.com/1.1/search/tweets.json?q=%23freebandnames&since_id=24012619984051000&max_id=250126199840518145&result_type=mixed&count=4 .

ただし、次のエラーが返されます。

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

これらのツイートを取得するにはどうすればよいですか?

Twitter.framework を使用したいのですが、何か提案をいただければ幸いです。

4

2 に答える 2

6

私は解決策を見つけました。Twitter は、ツイートを取得するために2 種類の認証を受け入れます。

  1. アプリケーションユーザー認証
  2. アプリケーションのみの認証 最初のタイプではログインとパスが必要で、2 番目のタイプでは必要ありませんが、bearer token.

最初、私のリクエストは次のように見えました:

NSURL *URL = [NSURL URLWithString:@"http://search.twitter.com/search.json?tag=ios&rpp=25"];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:URL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30.0];   
NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:nil];

これで、次のようになります。

if(self.bearerToken == nil) return;
NSURL *URL = [NSURL URLWithString:@"https://api.twitter.com/1.1/search/tweets.json?q=%%23ios&count=25"];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:URL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30.0];
[urlRequest setValue:[NSString stringWithFormat:@"Bearer %@", self.bearerToken] forHTTPHeaderField:@"Authorization"];
NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:nil];

また、このメソッドには、次の 2 つのメソッドを追加する必要がbearerTokenあり_base64Encodeます。

- (NSString *)bearerToken
{
    if(_bearerToken == nil)
    {
        NSString * consumerKey = [config.consumerKey stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        NSString * consumerSecret = [config.consumerSecret stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

        //the combined authentication key is "CONSUMER_KEY:CONSUMER_SECRET" run through base64 encoding.
        //we'll use NSData instead of NSString here so that we can feed it directly to the HTTPRequest later.
        NSString * combinedKey = [[self class] _base64Encode:[[NSString stringWithFormat:@"%@:%@", consumerKey, consumerSecret] dataUsingEncoding:NSUTF8StringEncoding]];

        NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://api.twitter.com/oauth2/token"]];
        [urlRequest setHTTPMethod:@"POST"];
        [urlRequest setValue:[NSString stringWithFormat:@"Basic %@", combinedKey] forHTTPHeaderField:@"Authorization"];
        [urlRequest setValue:[NSString stringWithFormat:@"application/x-www-form-urlencoded;charset=UTF-8"] forHTTPHeaderField:@"Content-Type"];
        [urlRequest setHTTPBody:[@"grant_type=client_credentials" dataUsingEncoding:NSUTF8StringEncoding]];
        NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:nil];
        NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
        _bearerToken = [responseJSON valueForKey:@"access_token"];
    }
    return _bearerToken;
}
+(NSString *)_base64Encode:(NSData *)data{
    //Point to start of the data and set buffer sizes
    int inLength = [data length];
    int outLength = ((((inLength * 4)/3)/4)*4) + (((inLength * 4)/3)%4 ? 4 : 0);
    const char *inputBuffer = [data bytes];
    char *outputBuffer = malloc(outLength);
    outputBuffer[outLength] = 0;

    //64 digit code
    static char Encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    //start the count
    int cycle = 0;
    int inpos = 0;
    int outpos = 0;
    char temp;

    //Pad the last to bytes, the outbuffer must always be a multiple of 4
    outputBuffer[outLength-1] = '=';
    outputBuffer[outLength-2] = '=';

    /* http://en.wikipedia.org/wiki/Base64
     Text content   M           a           n
     ASCII          77          97          110
     8 Bit pattern  01001101    01100001    01101110

     6 Bit pattern  010011  010110  000101  101110
     Index          19      22      5       46
     Base64-encoded T       W       F       u
     */


    while (inpos < inLength){
        switch (cycle) {
            case 0:
                outputBuffer[outpos++] = Encode[(inputBuffer[inpos]&0xFC)>>2];
                cycle = 1;
                break;
            case 1:
                temp = (inputBuffer[inpos++]&0x03)<<4;
                outputBuffer[outpos] = Encode[temp];
                cycle = 2;
                break;
            case 2:
                outputBuffer[outpos++] = Encode[temp|(inputBuffer[inpos]&0xF0)>> 4];
                temp = (inputBuffer[inpos++]&0x0F)<<2;
                outputBuffer[outpos] = Encode[temp];
                cycle = 3;
                break;
            case 3:
                outputBuffer[outpos++] = Encode[temp|(inputBuffer[inpos]&0xC0)>>6];
                cycle = 4;
                break;
            case 4:
                outputBuffer[outpos++] = Encode[inputBuffer[inpos++]&0x3f];
                cycle = 0;
                break;
            default:
                cycle = 0;
                break;
        }
    }
    NSString *pictemp = [NSString stringWithUTF8String:outputBuffer];
    free(outputBuffer);
    return pictemp;
}

レスポンスも変わったのでパーサーも変えました。前のバージョン:

NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithString:jsonStr];
if (responseDictionary)
{
    id data = responseDictionary[@"results"];
    if ([data isKindOfClass:NSArray.class])
    {
        NSArray *dataArray = (NSArray*)data;
        for (NSDictionary *post in dataArray)
        {
                avatarUrl = post[@"profile_image_url"];
            author = post[@"from_user"];
            message = post[@"text"];

                NSDateFormatter *inputFormatter = [[NSDateFormatter alloc] init];
                [inputFormatter setDateFormat:@"EEE',' dd MMM yyyy HH:mm:ss ZZZZ"];
            date = [inputFormatter dateFromString: post[@"created_at"]];
        }
    }
}

現行版:

NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithString:jsonStr];
if (responseDictionary)
{
    id data = [responseDictionary valueForKey:@"statuses"];
    if ([data isKindOfClass:NSArray.class])
    {
        NSArray *dataArray = (NSArray*)data;
        for (NSDictionary *post in dataArray)
        {               
            avatarUrl = post[@"user"][@"profile_image_url"];
            author = post[@"user" ][@"name"];;
            message = post[@"text"];         
                    NSDateFormatter *inputFormatter = [[NSDateFormatter alloc] init];
                    [inputFormatter setDateFormat:@"EEE MMM dd HH:mm:ss ZZZZ yyyy"];
                date = [inputFormatter dateFromString: post[@"created_at"]];
        }
    }
}
于 2013-10-31T06:37:40.067 に答える