Cannot AddObject to NSMutableArray from Block

拈花ヽ惹草 提交于 2020-01-22 01:59:05

问题


I have a feeling that my problem here is really with blocking, but maybe it's something else too. I am trying to forward geocode an address and place the coordinates into an array to use later.

An exception is raised down at the bottom when I try to call on one of the objects I tried added to the array in the block. The exception also gets raised before any of the NSLogs ever print out within the block text.

What's the proper way to handle this? Thanks.

 - (NSMutableArray *)convertAddressToGeocode:(NSString *)addressString
{
    //return array with lat/lng
    __block NSMutableArray *coordinates = [[NSMutableArray alloc] initWithCapacity:0];
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];

    [geocoder geocodeAddressString:addressString
             completionHandler:^ (NSArray* placemarks, NSError* error) {
                 for (CLPlacemark* aPlacemark in placemarks)
                 {
                     // Process the placemark.
                     if (error){
                         NSLog(@"Geocode failed with error: %@", error);
                         [self displayError:error];
                         return;
                     }
                     else {

                         NSArray const *keys = @[@"coordinate.latitude",
                                                 @"coordinate.longitude",
                                                 @"altitude",
                                                 @"horizontalAccuracy",
                                                 @"verticalAccuracy",
                                                 @"course",
                                                 @"speed",
                                                 @"timestamp"];

                         NSString *keylat = keys[0];
                         NSString *keylng = keys[1];

                         if (aPlacemark.location == nil)
                         {
                             NSLog(@"location is nil.");

                         }
                         else if ([keylat isEqualToString:@"coordinate.latitude"] && [keylng isEqualToString:@"coordinate.longitude"])
                         {
                             NSString *lat = @"";
                             NSString *lng = @"";
                             lat = [self displayStringForDouble: [aPlacemark.location coordinate].latitude];
                             lng = [self displayStringForDouble: [aPlacemark.location coordinate].longitude];

                             NSLog(@"This never gets executed"): //THIS NEVER GETS EXECUTED
                             [coordinates addObject:[NSString stringWithFormat:@"%@",lat]];
                             [coordinates addObject:[NSString stringWithFormat:@"%@",lng]];
                         }}}}];
NSLog(@"Array: %@", coordinates[0]);  //EXCEPTION RAISED HERE, Nothing ever gets added
return coordinates;
}

Here is the code this method is supposed to be plugged into, but I'm not getting the coordinates out of convertAddresstoGeocode to pass to convertCoordinatestoRepModel:

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    NSString *addressToSearch = self.addressSearchField.text;
    NSMutableArray *coordinateArray = [self convertAddressToGeocode:addressToSearch];
    NSMutableArray *repModelArray = [self convertCoordinatesToRepModel:coordinateArray];
...
}

回答1:


if geocodeAddressString is async operation than your block will be performed after

NSLog(@"Array: %@", coordinates[0]);

also, after call of your method ends (when event already handled) the coordinates array released (it is because of __block modifier - blocks do not retain objects with __block modifier), and in your block you try to use dealloced coordinates array.

Once again:

Your block will be called after NSLog(@"Array: %@", coordinates[0]);

f.e.:

  1. Remove NSLog(@"Array: %@", coordinates[0]); - it is normal that in that moment array is empty.
  2. Store your coordinates array in some @property , you can release it after using in block

UPDATE:

in .h file

typedef void (^ConverteArrayCallback)(NSArray *coordinates); 

under @intrerface

- (void)convertAddressToGeocode:(NSString *)addressString callback:(ConverteArrayCallback) callback;

in .m file

- (void)convertAddressToGeocode:(NSString *)addressString callback:(ConverteArrayCallback) callback { 
    NSMutableArray *coordinates = [[NSMutableArray alloc] initWithCapacity:0];
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];

    [geocoder geocodeAddressString:addressString
             completionHandler:^ (NSArray* placemarks, NSError* error) {
                 for (CLPlacemark* aPlacemark in placemarks)
                 {
                     // Process the placemark.
                     if (error){
                         NSLog(@"Geocode failed with error: %@", error);
                         [self displayError:error];
                         return;
                     }
                     else {

                         NSArray const *keys = @[@"coordinate.latitude",
                                                 @"coordinate.longitude",
                                                 @"altitude",
                                                 @"horizontalAccuracy",
                                                 @"verticalAccuracy",
                                                 @"course",
                                                 @"speed",
                                                 @"timestamp"];

                         NSString *keylat = keys[0];
                         NSString *keylng = keys[1];

                         if (aPlacemark.location == nil)
                         {
                             NSLog(@"location is nil.");

                         }
                         else if ([keylat isEqualToString:@"coordinate.latitude"] && [keylng isEqualToString:@"coordinate.longitude"])
                         {
                             NSString *lat = @"";
                             NSString *lng = @"";
                             lat = [self displayStringForDouble: [aPlacemark.location coordinate].latitude];
                             lng = [self displayStringForDouble: [aPlacemark.location coordinate].longitude];

                                 NSLog(@"This never gets executed"): //THIS NEVER GETS EXECUTED
                                 [coordinates addObject:[NSString stringWithFormat:@"%@",lat]];
                                 [coordinates addObject:[NSString s

tringWithFormat:@"%@",lng]];
                                 }}}

                           if (callback != NULL) {
                                 callback(coordinates);
                           }

      }];
}

That should works!

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    NSString *addressToSearch = self.addressSearchField.text;
    [self convertAddressToGeocode:addressToSearch callback:^(NSArray *coordinates)
      {  
       self.textView.text = [coordinates objectAtIndex:0];
      }];
}



回答2:


__block NSMutableArray *coordinates = [[NSMutableArray alloc] initWithCapacity:0];

The problem is here; just replace the above code with:

NSMutableArray *coordinates = [[NSMutableArray alloc] init];


来源:https://stackoverflow.com/questions/19287737/cannot-addobject-to-nsmutablearray-from-block

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