2012-06-06 5 views
5

Also versuche ich die integrierte Twitter-API in iOS 5 zu verwenden, um eine Liste aller Follower für einen bestimmten Benutzer abzurufen. In der gesamten Beispieldokumentation, die ich finden kann, werden Anfragen an die API gestellt, die Inline - Blöcke weiterleitet, die ausgeführt werden, wenn die Anfrage zurückkehrt, was für die meisten einfacheren Sachen gut ist, ABER wenn ich versuche, ~ 1000 Follower zu bekommen Anfrage gibt sie in Größe ~ 100 ausgelagert zurück, ich bin fest, wie rekursiv die Anfrage erneut aufrufen mit der 'nächsten Paging-Adresse' zurückgegeben und verarbeitet im Abschlussblock. Hier ist der Code:Verwenden von Objective-C-Blöcken rekursiv mit iOS Twitter-API

- (void)getTwitterFollowers { 
    // First, we need to obtain the account instance for the user's Twitter account 
    ACAccountStore *store = [[ACAccountStore alloc] init]; 
    ACAccountType *twitterAccountType = 
    [store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter]; 

    // Request access from the user for access to his Twitter accounts 
    [store requestAccessToAccountsWithType:twitterAccountType 
        withCompletionHandler:^(BOOL granted, NSError *error) { 
     if (!granted) { 
      // The user rejected your request 
      NSLog(@"User rejected access to his account."); 
     } 
     else { 
      // Grab the available accounts 
      NSArray *twitterAccounts = 
      [store accountsWithAccountType:twitterAccountType]; 

      if ([twitterAccounts count] > 0) { 
       // Use the first account for simplicity 
       ACAccount *account = [twitterAccounts objectAtIndex:0]; 

       // Now make an authenticated request to our endpoint 
       NSMutableDictionary *params = [[NSMutableDictionary alloc] init]; 
       [params setObject:@"1" forKey:@"include_entities"]; 

       // The endpoint that we wish to call 
       NSURL *url = [NSURL URLWithString:@"http://api.twitter.com/1/followers.json"]; 

       // Build the request with our parameter 
       request = [[TWRequest alloc] initWithURL:url 
              parameters:params 
             requestMethod:TWRequestMethodGET]; 

       [params release]; 

       // Attach the account object to this request 
       [request setAccount:account]; 

       [request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) { 
        if (!responseData) { 
         // inspect the contents of error 
         FullLog(@"%@", error); 
        } 
        else { 
         NSError *jsonError; 
         followers = [NSJSONSerialization JSONObjectWithData:responseData 
                    options:NSJSONReadingMutableLeaves 
                    error:&jsonError];    
         if (followers != nil) {       
          // THE DATA RETURNED HERE CONTAINS THE NEXT PAGE VALUE NEEDED TO REQUEST THE NEXT 100 FOLLOWERS, 
          //WHAT IS THE BEST WAY TO USE THIS?? 
          FullLog(@"%@", followers); 
         } 
         else { 
          // inspect the contents of jsonError 
          FullLog(@"%@", jsonError); 
         } 
        } 
       }];   
      } // if ([twitterAccounts count] > 0) 
     } // if (granted) 
    }]; 
    [store release]; 
} 

Im Idealfall würde ich irgendwie gerne hören für diese Daten zurückgegeben werden, überprüfen Sie für eine nächste Seite Wert und wenn es vorhanden ist, wiederverwenden den Codeblock und fügen die Daten zurückgegeben. Ich bin mir sicher, dass es einen Best-Practice-Weg geben muss, um dies zu erreichen, jede Hilfe wäre sehr willkommen!

+0

offtopic: ist die "Follower", die Sie in der Anfrage performRequestWithHandler Methode eine iVar verwenden? – CarlJ

+0

Ja, es ist ein 'NSArray' –

+0

und wo hast du es definiert? – CarlJ

Antwort

3

zu erweitern auf @Eimantas' Antwort wird Ihre Anfrage Handler eine bestimmte Blocksignatur erwarten, so dass Sie eine andere Art und Weise müssen die Seitennummer zu behandeln.

-(void)getTwitterFollowers { 
    // set up request... 
    __block int page = 0; 
    __block void (^requestHandler)(NSData*, NSHTTPURLResponse*, NSError*) = null; 
    __block TWRequest* request = [[TWRequest alloc] initWithURL:url 
                parameters:params 
                requestMethod:TWRequestMethodGET]; 
    requestHandler = [^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) { 
     followers = [NSJSONSerialization JSONObjectWithData:responseData 
              options:NSJSONReadingMutableLeaves 
              error:&jsonError];    
     if (followers != nil) {       
      // process followers 
      page++; 
      NSMutableDictionary *params = [NSMutableDictionary dictionaryWithDictionary:request.parameters]; 
      // update params with page number 
      request = [[TWRequest alloc] initWithURL:url 
              parameters:params 
             requestMethod:TWRequestMethodGET]; 
      [request performRequestWithHandler:requestHandler]; 
     } 
    } copy]; 

    // now call the block for the first page 
    [request performRequestWithHandler:requestHandler]; 
} 
5

Um einen Block rekursiv zu verwenden, müssen Sie ihn zuerst deklarieren und später definieren. Versuchen Sie folgendes:

__block void (^requestPageBlock)(NSInteger pageNumber) = NULL; 

requestPageBlock = [^(NSInteger pageNumber) { 
    // do request with some calculations 
    if (nextPageExists) { 
     requestPageBlock(pageNumber + 1); 
    } 
} copy]; 

// now call the block for the first page 
requestPageBlock(0); 
+3

Sie müssen nicht deklarieren es zuerst. Aber ich glaube, Sie müssen die Blockvariable als __block angeben und den Block in den Stapel kopieren, bevor Sie rekursiv auf ihn verweisen. Andernfalls erhalten Sie eine EXC_BAD_ACCESS. Also .. '__block void (^ Anfrage) (NSUInteger) = [^ (NSUInteger Seite) {..... Code ......} Kopie];' –

+1

Sie haben Recht! Danke für die Lösung. – Eimantas

+2

Kein Problem. Ich habe ziemlich viel Zeit damit verbracht, das herauszufinden. Seien Sie auch sehr vorsichtig, wenn Sie innerhalb eines rekursiven Blocks auf einen anderen Block verweisen. Sie tun dies nicht in Ihrem Beispiel, aber es ist ein kleiner Schritt weg und es kann zu Speicherlecks führen .... siehe hier: http://Stackoverflow.com/a/8896766/1147934 –

Verwandte Themen