0

Google からの JSON を解析して、マップに注釈を付けようとしています。AFNetworking を使用した JSON の解析と解析プロセスは、Singleton クラスにあります。2 つの異なる 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];
}

問題は、注釈を表示するブレークポイントを使用して初めて詳細クラスにあり、2 番目にエラーが発生します。

-[__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して、Google からの json 応答を解析しました。

このメソッドでは、NSMutable Data オブジェクト (Google 応答からのデータを追加して作成された _routeData) を解析します。

- (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];
  }
}

Google からのポリライン ポイントの応答をデコードするために、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 に答える