Variable returning null after block execution

2019-03-05 07:04发布

问题:

I am dispatching a queue to download some flickr photos on a separate thread (in viewWillAppear). When I log the contents of the array inside the block, it shows everything perfectly:

    dispatch_queue_t photoDowonload=dispatch_queue_create("photoDownload", NULL);
dispatch_async(photoDowonload, ^{

    NSArray *photoList=[FlickrFetcher topPlaces]; //downloads flickr data
    self.listOfCities=photoList;
    NSLog(@"inside block: %@", self.listOfCities); //shows contents

});

but when I try to log the array that was set inside the block outside the block, it returns null.

    dispatch_queue_t photoDowonload=dispatch_queue_create("photoDownload", NULL);
dispatch_async(photoDowonload, ^{

    NSArray *photoList=[FlickrFetcher topPlaces];
    self.listOfCities=photoList;

});

    NSLog(@"after block: %@", self.listOfCities); //returns null

What's the problem here? self.listOfCities is set up as NSArray property so once it's set in the block, it should be accessible outside of it.

回答1:

The code in the block is run asynchronously. So the code after the block is run before the code in the block has had a chance to run (or certainly complete at least).



回答2:

I've just started learning Objective-c, and I can be blind for some kind of issues but I'm wondering what is the impact of the _dispatch_asynch_ on executing block of code shown above. Docs says

The dispatch_async() and dispatch_sync() functions schedule blocks for concurrent execution within the dispatch framework.

Maybe NSLog is called before execution of code block and variable is not initialized yet.

@rmaddy You was faster.



回答3:

Ok I figured this out. My goal was to update the tableView with the info returned by block.

The block execution was changing the array variable but that change was not getting shown.

The trick was to detect this change in the getter for the array as follows:

-(void) setListOfCities:(NSArray *)listOfCities
{
    if (_listOfCities!=listOfCities)
    {
        _listOfCities=listOfCities;
        [self.tableView reloadData]; //<-- reloads table after change
    }
}