iOS - prepareForSegue doesn't wait for the completionBlock to be completed

╄→尐↘猪︶ㄣ 提交于 2019-12-24 18:37:18

问题


What I like: Wait until data download completes then open TableView and show data.

What I have: When prepareForSegue is called the TableView opens immediately without waiting for the data download although I have a completionBlock (which may not be implemented correctly I guess).

Note: When I go back and open the TableView again I see the data.

- (void)fetchEntries
{
    void (^completionBlock) (NSArray *array, NSError *err) = ^(NSArray *array, NSError *err)
    {
        if (!err)
        {
            self.articlesArray = [NSArray array];
            self.articlesArray = array;
        }
    };

    [[Store sharedStore] fetchArticlesWithCompletion:completionBlock];
}


-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    [self fetchEntries];

    if ([[segue identifier] isEqualToString:@"ShowArticles"])
    {
        TableVC *tbc = segue.destinationViewController;
        tbc.articlesArrayInTableVC = self.articlesArray;
    }

}

Store.m

- (void)fetchArticlesWithCompletion:(void (^) (NSArray *channelObjectFromStore, NSError *errFromStore))blockFromStore
{
    NSString *requestString = [API getLatestArticles];

    NSURL *url = [NSURL URLWithString:requestString];

    NSURLRequest *req = [NSURLRequest requestWithURL:url];

    Connection *connection = [[Connection alloc] initWithRequest:req];

    [connection setCompletionBlockInConnection:blockFromStore];

    [connection start];
}

回答1:


You should load your data before you perform a seque.

- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // show loading indicator
    __weak typeof(self) weakSelf = self;
    [[Store sharedStore] fetchArticlesWithCompletion:^(NSArray *array, NSError *err)
    {
        [weakSelf performSegueWithIdentifier:@"ShowArticles" sender:weakSelf];
        // hide loading indicator
    }];
}

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // do whatever
}

Although in my opinion it is much nicer to immediately show the next view controller in response to a user interaction. Have you considered loading your data in the next view controller, instead of waiting for it before you actually want to transition?




回答2:


I still recommend Joris' answer more than this, but in theory, you could do something funky like:

- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
    if ([identifier isEqualToString:@"segueIdentifier"] && !_didFinishExecutingBlock)
    {
        [self methodWithCompletionBlock:^{
            _didFinishExecutingBlock = YES;
            [self.navigationController performSegueWithIdentifier:identifier sender:self];
        }];
        return false;
    }
    else
        return true;
}



回答3:


It's not going to wait since you are using a block and that is executed as soon as it's declaration is done, a solution would be to remove the block

- (void)fetchEntries
{
        if (!err)
        {
            self.articlesArray = [NSArray array];
            self.articlesArray = array;
        }


    [[Store sharedStore] fetchArticlesWithCompletion:completionBlock];
}


-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    [self fetchEntries];

    if ([[segue identifier] isEqualToString:@"ShowArticles"])
    {
        TableVC *tbc = segue.destinationViewController;
        tbc.articlesArrayInTableVC = self.articlesArray;
    }

}


来源:https://stackoverflow.com/questions/14506559/ios-prepareforsegue-doesnt-wait-for-the-completionblock-to-be-completed

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