marcshilling
marcshilling

Reputation: 1445

EXC_BAD_ACCESS when calling a block recursively

I'm working with the new iOS Spotify SDK. I need to fetch ALL of a user's saved tracks for my application. Results are paginated. As such, I am attempting to use requestNextPageWithSession: callback: recursively until I've fetched all the pages.

First, I make the initial request for saved tracks. This returns the first page successfully, so if there are additional pages, I call getNextPage()

__block SPTListPage *allPages;
[SPTRequest savedTracksForUserInSession:session callback:^(NSError *error, SPTListPage *firstPage) {
   if (!error) {
      allPages = firstPage;
      if (firstPage.hasNextPage) {
         getNextPage(firstPage);
      }
      else {
         // All tracks were in the first page
      }
   }
}];

getNextPage() is declared as a block above, like so:

Block getNextPage;
getNextPage = ^(SPTListPage *page) {
    [page requestNextPageWithSession:session callback:^(NSError *error, SPTListPage *nextPage) {
        if (!error) {
            [allPages pageByAppendingPage:nextPage];
            if (nextPage.hasNextPage) {
                getNextPage(nextPage);
            }
            else {
                // Got all pages
            }
        }
    }];
};

FYI - I've defined "Block" as such for use globally:

typedef void (^Block)();

The issue is the first time I attempt to use getNextPage() recursively within the block, it crashes with EXC_BAD_ACCESS on that line. The stacktrace isn't helpful, but it appears like getNextPage is released. Hoping someone has tackled a similar issue.

Upvotes: 0

Views: 449

Answers (1)

Ian MacDonald
Ian MacDonald

Reputation: 14020

You'd have to save a reference to your block or it'll get cleaned up when execution reaches the end of the scope. You could create a property on your class that holds it.

@property (nonatomic, copy) Block block;

Alternatively, you could just use methods.

- (void)fetchNextPage:(SPTListPage *)page {
  [page requestNextPageWithSession:session callback:^(NSError *error, SPTListPage *nextPage) {
    if (!error) {
      [allPages pageByAppendingPage:nextPage];
      if (nextPage.hasNextPage) {
        [self fetchNextPage:nextPage];
      }
      else {
        // Got all pages
      }
    }
  }];
}

Upvotes: 1

Related Questions