0

我正在尝试解析来自 Google 的 JSON 以在 Map 上放置注释。使用 AFNetworking 解析 JSON 和解析过程在 Singleton 类中。我从两个不同的 JSON 中获取值。

  1. Google 的地方自动填充 JSON
  2. Google 的地点详情 JSON

这是我的单例类代码

-(void)getData:(NSString *)searchString
{
    _dataArray = [[NSMutableArray alloc]init];


    NSString *requestString = [[NSString alloc]init];
    requestString = [NSString stringWithFormat:@"https://maps.googleapis.com/maps/api/place/autocomplete/json?input=%@&sensor=true&key=APIKEY",searchString];
    requestString = [requestString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL *URL = [NSURL URLWithString:requestString];

    NSURLRequest *requestURL = [NSURLRequest requestWithURL:URL];

    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:requestURL success:^(NSURLRequest *requestURL,NSHTTPURLResponse *response, id JSON){
        self.dataArray = [JSON objectForKey:@"predictions"];

        [[NSNotificationCenter defaultCenter]postNotificationName:@"Doreload" object:nil];

    }failure:^(NSURLRequest *requestURL,NSHTTPURLResponse *response,NSError *error, id JSON){
        NSLog(@"Request Failed with Error: %@, %@", error, error.userInfo);
    }];

    [operation start];
}



    -(void)detailList:(NSString *)referenceString
    {
        _detailArray = [[NSMutableArray alloc]init];

        NSString *requestString = [[NSString alloc]initWithFormat:@"https://maps.googleapis.com/maps/api/place/details/json?reference=%@&sensor=true&key=APIKEY",referenceString];

        NSURL *URL = [NSURL URLWithString:requestString];

        NSURLRequest *requestURL = [NSURLRequest requestWithURL:URL];

        AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:requestURL success:^(NSURLRequest *requestURL,NSHTTPURLResponse *response, id JSON){

            self.detailArray = [JSON objectForKey:@"result"];

            [[NSNotificationCenter defaultCenter]postNotificationName:@"showList" object:nil];

        }failure:^(NSURLRequest *requestURL,NSHTTPURLResponse *response,NSError *error, id JSON){

        }];

        [operation start];
    }

在具有第一个函数的 ViewController 中,我在 tableView 中传递 Place 的名称:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   sharedRequest = [RequestHandler sharedRquest];

    static NSString *cellID = @"Cell Identifier";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    if (cell == nil) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
    }

    cell.textLabel.text = [[sharedRequest.dataArray objectAtIndex:indexPath.row]objectForKey:@"description"];

    [_spinner stopAnimating];

    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    DetailViewController *details = [[DetailViewController alloc]initWithNibName:@"DetailViewController" bundle:nil];

    details.stringReference = [[sharedRequest.dataArray objectAtIndex:indexPath.row]objectForKey:@"reference"];

    [self.navigationController pushViewController:details animated:YES];

    [tableView deselectRowAtIndexPath:indexPath animated:YES];

}

详细信息类是:

- (void)viewDidLoad
{
    [super viewDidLoad];

    [[RequestHandler sharedRquest]detailList:self.stringReference];

    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(showOnMap) name:@"showList" object:nil];

    self.spinner = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    self.spinner.hidesWhenStopped = YES;
    self.spinner.frame = CGRectMake(0, 0, 320, 480);
    [self.view addSubview:_spinner];
    [_spinner startAnimating];

    self.mapView.showsUserLocation = TRUE;
    self.mapView.delegate = self;
}


- (void)showOnMap:(NSNotification *)notification
{
    NSLog(@"Entered");

    sharedRequest = [RequestHandler sharedRquest];

    NSString *string = [[NSString alloc]init];

    string = [sharedRequest.detailArray valueForKey:@"name"];

    self.label.text = string;
}

-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
    sharedRequest = [RequestHandler sharedRquest];

    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 30000, 30000);
    [self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];

    double latitude = [[[[sharedRequest.detailArray valueForKey:@"geometry"]objectForKey:@"location"]objectForKey:@"lat"]doubleValue];
    double longitude =[[[[sharedRequest.detailArray valueForKey:@"geometry"]objectForKey:@"location"]objectForKey:@"lng"]doubleValue];


    CLLocationCoordinate2D coord = { latitude, longitude };

    MKPointAnnotation *point = [[MKPointAnnotation alloc]init];
    point.coordinate = coord;
    point.title = [sharedRequest.detailArray valueForKey:@"name"];
    [self.mapView addAnnotation:point];

    [_spinner stopAnimating];
}

问题第一次出现在详细信息类中,当使用断点时,它显示注释,然后出现错误:

-[__NSArrayI objectForKey:]: unrecognized selector sent to instance 0x86332e0

编辑:

这是 shared.detailArray 的内容:

"address_components" =     (
                {
            "long_name" = Francestown;
            "short_name" = Francestown;
            types =             (
                locality,
                political
            );
        },
                {
            "long_name" = Hillsborough;
            "short_name" = Hillsborough;
            types =             (
                "administrative_area_level_2",
                political
            );
        },
                {
            "long_name" = "New Hampshire";
            "short_name" = NH;
            types =             (
                "administrative_area_level_1",
                political
            );
        },
                {
            "long_name" = "United States";
            "short_name" = US;
            types =             (
                country,
                political
            );
        }
    );
    "adr_address" = "<span class=\"locality\">Francestown</span>, <span class=\"region\">NH</span>, <span class=\"country-name\">USA</span>";
    "formatted_address" = "Francestown, NH, USA";
    geometry =     {
        location =         {
            lat = "42.9875";
            lng = "-71.8130599";
        };
        viewport =         {
            northeast =             {
                lat = "43.03844";
                lng = "-71.7474139";
            };
            southwest =             {
                lat = "42.949703";
                lng = "-71.88583609999999";
            };
        };
    };
    icon = "http://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png";
    id = ccd239475516163d29405af62fb286bedb4c6377;
    name = Francestown;
    reference = "CoQBcwAAAPSQxzNrepzPywLZr1PDoPEmQmGR8rIPTPoQ_f2kXpceRGHU_J_FEcrDxZSzebqLRpNYlUC_-xRJVV7Jx_mW1KJ33foU9y0ZCNK_kC1orqZVK5B-EONPD_Ef_e9WXXZdfOZTBQzNYLhoVdP8Ufa1bPe_vuuwe3rqYtf80IyANb8mEhCKi6kISip4ItpBFfgWjuGvGhSj0hURZaTQXX4lnFlxe2v4O5Uo6Q";
    types =     (
        locality,
        political
    );
    url = "https://maps.google.com/maps/place?q=Francestown&ftid=0x89e22c36ba6dc937:0x52cccc5f0f9b8663";
    vicinity = Francestown;
}

我尝试了很多来理解错误,但都是徒劳的。

任何帮助都是不言而喻的。

谢谢

4

3 回答 3

0

如果您希望使用不同的方式获得结果,希望这会对您有所帮助。我使用NSJSONSerialization类来解析来自谷歌的 json 响应。

在此方法中,我解析 NSMutable Data 对象-_routeData(通过附加来自 Google 响应的数据创建)

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
  NSMutableArray *polyLinesArray = [[NSMutableArray alloc] init];
  NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:_routeData options:kNilOptions error:nil];
  NSArray *locationArray = [[[[[jsonDict valueForKey:@"routes"]valueForKey:@"legs"]valueForKey:@"steps"]valueForKey:@"polyline"] valueForKey:@"points"];
  if(locationArray.count > 0)
  {
    NSArray *polyLinePointsArray = [[locationArray objectAtIndex:0]objectAtIndex:0];
    for (int i = 0; i < [polyLinePointsArray count]; i++)
    {
      NSString *encodedPoints = [polyLinePointsArray objectAtIndex:i];
      MKPolyline *route = [self polylineWithEncodedString:encodedPoints];
      [polyLinesArray addObject:route];
    }
    // remove previous overlays
    if(_mapView.overlays.count > 0)
    {
      [_mapView removeOverlays:_mapView.overlays];
    }
    [self.mapView addOverlays:polyLinesArray];
  }
}

为了解码来自谷歌的折线点响应,我使用了我在 stackoverflow 上找到的一个类。

- (MKPolyline *)polylineWithEncodedString:(NSString *)encodedString
{
  const char *bytes = [encodedString UTF8String];
  NSUInteger length = [encodedString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
  NSUInteger idx = 0;

  NSUInteger count = length / 4;
  CLLocationCoordinate2D *coords = calloc(count, sizeof(CLLocationCoordinate2D));
  NSUInteger coordIdx = 0;

  float latitude = 0;
  float longitude = 0;
  while (idx < length) {
    char byte = 0;
    int res = 0;
    char shift = 0;

    do {
      byte = bytes[idx++] - 63;
      res |= (byte & 0x1F) << shift;
      shift += 5;
    } while (byte >= 0x20);

    float deltaLat = ((res & 1) ? ~(res >> 1) : (res >> 1));
    latitude += deltaLat;

    shift = 0;
    res = 0;

    do {
      byte = bytes[idx++] - 0x3F;
      res |= (byte & 0x1F) << shift;
      shift += 5;
    } while (byte >= 0x20);

    float deltaLon = ((res & 1) ? ~(res >> 1) : (res >> 1));
    longitude += deltaLon;

    float finalLat = latitude * 1E-5;
    float finalLon = longitude * 1E-5;

    CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(finalLat, finalLon);
    coords[coordIdx++] = coord;

    if (coordIdx == count) {
      NSUInteger newCount = count + 10;
      coords = realloc(coords, newCount * sizeof(CLLocationCoordinate2D));
      count = newCount;
    }
  }

  MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:coordIdx];
  free(coords);

  return polyline;
}
于 2013-06-11T13:15:19.503 回答
0

而不是这个

double latitude = [[[[sharedRequest.detailArray valueForKey:@"geometry"]objectForKey:@"location"]objectForKey:@"lat"]doubleValue];
double longitude =[[[[sharedRequest.detailArray valueForKey:@"geometry"]objectForKey:@"location"]objectForKey:@"lng"]doubleValue];

尝试这个,

double latitude = [[[[sharedRequest.detailArray valueForKey:@"geometry"]valueForKey:@"location"]valueForKey:@"lat"]doubleValue];
double longitude =[[[[sharedRequest.detailArray valueForKey:@"geometry"]valueForKey:@"location"]valueForKey:@"lng"]doubleValue];
于 2013-06-11T13:17:04.900 回答
0

找到解决方案:

- (void)showOnMap:(NSNotification *)notification
{
    NSLog(@"Entered");

    sharedRequest = [RequestHandler sharedRquest];

    NSString *string = [[NSString alloc]init];

    string = [sharedRequest.detailArray valueForKey:@"name"];

    self.label.text = string;

    double latitude = [[[[sharedRequest.detailArray valueForKey:@"geometry"]objectForKey:@"location"]objectForKey:@"lat"]doubleValue];
    double longitude =[[[[sharedRequest.detailArray valueForKey:@"geometry"]objectForKey:@"location"]objectForKey:@"lng"]doubleValue];


    CLLocationCoordinate2D coord = { latitude, longitude };

    MKPointAnnotation *point = [[MKPointAnnotation alloc]init];
    point.coordinate = coord;
    point.title = [sharedRequest.detailArray valueForKey:@"name"];
    [self.mapView addAnnotation:point];

    [_spinner stopAnimating];
}

-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
    sharedRequest = [RequestHandler sharedRquest];

    MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 30000, 30000);
    [self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
}
于 2013-06-12T06:35:44.377 回答