使用iOS Twitter API递归使用objective-c块

Sam*_*low 5 twitter recursion objective-c ios objective-c-blocks

因此,我尝试使用iOS 5中内置的Twitter API来检索给定用户的所有关注者列表.在我可以找到的所有示例文档中,请求API传递在请求返回时要执行的内联块,这对于大多数更简单的东西来说都很好,但是当我试图获得~1000个粉丝时,请求返回大小为~100的页面,我仍然坚持如何使用在完成块内返回并处理的"下一个寻呼地址"再次递归调用请求.这是代码:

- (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];
}
Run Code Online (Sandbox Code Playgroud)

理想情况下,我想要一些方法来监听返回的数据,检查下一页的值是否存在,重用代码块并附加返回的数据.我确定必须有一种"最佳实践"方式来实现这一目标,我们将非常感谢任何帮助!

Eim*_*tas 5

要递归使用任何块,您必须先声明它并稍后定义它.试试这个:

__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);
Run Code Online (Sandbox Code Playgroud)

  • 您不必先声明它.但我相信您需要将块变量指定为__block,并在递归引用自身之前将块复制到堆栈.否则你会得到一个EXC_BAD_ACCESS.所以......`__block void(^ request)(NSUInteger)= [^(NSUInteger page){..... code ......} copy];` (3认同)
  • 没问题.我花了很多时间搞清楚这一点.另外,如果从递归块中引用另一个块,请务必小心.你不是在你的例子中这样做,但它只是一小步,它可能导致内存泄漏....见这里:http://stackoverflow.com/a/8896766/1147934 (2认同)

Chr*_*lay 3

为了扩展@Eimantas的答案,您的请求处理程序需要特定的块签名,因此您需要一种不同的方式来处理页码。

-(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];
}
Run Code Online (Sandbox Code Playgroud)