Recursive Blocks and a Bad Memory Leak

纵然是瞬间 提交于 2019-12-11 20:36:54

问题


I am using recursive blocks to fetch tweets via the Twitter API and do encounter a bad memory leak: 50 recursive fetches lead to a memory footprint > 500 MB.

This method is called from inside my view controller and controls the lists of which the timelines should be fetched:

    - (void)fetchTweetsForUsersInList:(List*)list withCompletionHandler:
                 (simpleCompletionBlock)completionBlock
{
     [self.managedDocument.managedObjectContext performBlock:^{

     NSFetchRequest *request = [NSFetchRequest 
          fetchRequestWithEntityName:@"User"];
     request.predicate = predicate;
     request.sortDescriptors = sortDescriptors;
     request.shouldRefreshRefetchedObjects = YES;

     NSError *error;
     NSArray *users = [self.managedDocument.managedObjectContext 
          executeFetchRequest:request error:&error];

     __weak __block void (^weakCompletion)(NSError*);
     __block void (^completion)(NSError*);

     __block NSUInteger i = 0;
     __block User *user = users[i];

     unsigned long long since_id = ....;
     unsigned long long maxId = ....;

     completion = ^(NSError *error) {

         if (i == users.count - 1 ) {

            completionBlock(nil); 

         }
         else {
            i++;
            user = users[i];

           [self fetchTimelineOfUser:user 
            sinceId:since_id maxId:maxId 
            withCompletionHandler:weakCompletion];
         }
       };

    weakCompletion = completion;
    [self fetchTimelineOfUser:user 
        sinceId:since_id maxId:maxId 
        withCompletionHandler:completion];
    }];
}

And this is fetchTimelineOfUser which is called recursively:

- (void)fetchTimelineOfUser:(User*)user 
    sinceId:(unsigned long long)since_id 
    maxId:(unsigned long long)maxId 
    withCompletionHandler:(simpleCompletionBlock)completionBlock
{
    TwitterRequest *twitterRequest = self.twitterRequest;

    NSUInteger count = 2000;

    __weak __block void (^weakCompletion)(NSError*, unsigned long long, NSArray*);
    __block void (^completion)(NSError*, unsigned long long, NSArray*);

    completion = ^(NSError *error, unsigned long long  minId, NSArray *tweets) {

        [self.managedDocument.managedObjectContext performBlockAndWait:^{

           [tweets enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

              // Create new Tweet object

              Tweet *tweet = [NSEntityDescription
                  insertNewObjectForEntityForName:@"Tweet"
                  inManagedObjectContext:self.managedDocument.managedObjectContext];
              tweet.text = [obj valueForKey:@"text"];

               NSError *saveError;
              [self.managedDocument.managedObjectContext save:&saveError];

                // (1) If no more tweets above since_id or the minimum 
                // tweet id has reached an existing tweet id, recursion is complete:

                if (tweets.count == 0 || minId - 1 == since_id) {

                    NSError *saveError;
                    [self.managedDocument.managedObjectContext 
                           save:&saveError];

                    [self.managedDocument.managedObjectContext 
                         performBlockAndWait:^{

                        [self.managedDocument saveToURL:self.managedDocument.fileURL
                                       forSaveOperation:UIDocumentSaveForOverwriting
                                      completionHandler:^(BOOL success) {

                                          completionBlock(nil);
                                          return;
                                      }];
                    }];
                }

                // (2) Otherwise RECURSIVELY call ...

                else {
                    [twitterRequest 
                       fetchTimelineForUser:user.screen_name 
                       sinceId:since_id maxId:minId-1 
                       count:count 
                       withCompletion:weakCompletion];
                }
            }];
        }
    };
    weakCompletion = completion;

    [twitterRequest fetchTimelineForUser:user.screen_name 
          sinceId:since_id maxId:maxId 
          count:count 
          withCompletion:completion];
}

Question:

Is it possible that I have a retain cycle or other memory leak? Do you have any idea why my memory footprint is so high?

Thank you!

来源:https://stackoverflow.com/questions/25312904/recursive-blocks-and-a-bad-memory-leak

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!