0

My code:

-(void)addressLocation:(NSArray *)inputData {
NSString *plusAddress = [[inputData objectAtIndex:0] stringByReplacingOccurrencesOfString:@" " withString:@"+"];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?address=%@,%@&sensor=false&region=pl", plusAddress, [inputData objectAtIndex:1]]];

__block CLLocationCoordinate2D newRecord;
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
    NSArray *results = [JSON valueForKey:@"results"];
    NSNumber *latNumber = [[results objectAtIndex:0] valueForKeyPath:@"geometry.location.lat"];
    NSNumber *lngNumber = [[results objectAtIndex:0] valueForKeyPath:@"geometry.location.lng"];
    CGFloat lat = [latNumber floatValue];
    CGFloat lng = [lngNumber floatValue];
    newRecord = CLLocationCoordinate2DMake(lat, lng);
}  failure:nil];
[operation start];
[operation waitUntilFinished];

KantorPoint *newPoint = [[KantorPoint alloc] init];
newPoint.coordinate = newRecord;
newPoint.name = [inputData objectAtIndex:1];
newPoint.address = [inputData objectAtIndex:0];
[self.pointersArray addObject:newPoint];
}

I'm trying to transmit newRecord from operation block as in this answer. But newPoint.coordinate is null and I can't do something like return newRecord inside block (get an error). Is there way to solve this problem?

Community
  • 1
  • 1
RomanHouse
  • 2,552
  • 3
  • 23
  • 44
  • I bet you're getting some kind of error in your JSON request. You don't pass in a `failure` block when you create `operation`. Do that, and see if it gets called. – Nate Jul 08 '12 at 14:21
  • my JSON request is fine. if inside block I do `NSLog(@"newRecord lat = %f",newRecord.latitude);` console shows me right value. – RomanHouse Jul 08 '12 at 14:26
  • Hmmm. Just curious. Why are you using an asynchronous request, if you want to wait on it to complete (essentially making it synchronous)? Is the code you posted simplified for the sake of asking the question? – Nate Jul 08 '12 at 14:28
  • AFJSONRequestOperation has an internal processing queue, i think the problem is, that the success block is called after the json processing has finished which happens after the operation itself finishes – Felix Jul 08 '12 at 14:30
  • @Nate hmm, you are right. but is there the way to doing synchronous request such nice as AF? – RomanHouse Jul 08 '12 at 14:44

1 Answers1

0

I'm not sure about your goal but I would rewrite the code in this manner.

- (void)addressLocation:(NSArray *)inputData {

    NSString *plusAddress = [[inputData objectAtIndex:0] stringByReplacingOccurrencesOfString:@" " withString:@"+"];
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?address=%@,%@&sensor=false&region=pl", plusAddress, [inputData objectAtIndex:1]]];

    __block YourClass *selfBlock = self; // __weak YourClass *selfBlock = self; if you use ARC

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

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

        NSArray *results = [JSON valueForKey:@"results"];
        NSNumber *latNumber = [[results objectAtIndex:0] valueForKeyPath:@"geometry.location.lat"];
        NSNumber *lngNumber = [[results objectAtIndex:0] valueForKeyPath:@"geometry.location.lng"];
        CGFloat lat = [latNumber floatValue];
        CGFloat lng = [lngNumber floatValue];
        CLLocationCoordinate2D newRecord = CLLocationCoordinate2DMake(lat, lng);

        KantorPoint *newPoint = [[KantorPoint alloc] init];
        newPoint.coordinate = newRecord;
        newPoint.name = [inputData objectAtIndex:1];
        newPoint.address = [inputData objectAtIndex:0];
        [selfBlock.pointersArray addObject:newPoint];

    }  failure:nil];

    // the queue needs to be allocated somewhere...
    [[self operationQueue] addOperation:operation];
}

Make attention if you use ARC: __block doesn't prevent the object to be retained. Use __weak instead.

Edit

Based on phix23, you need to retain your operation somewhere. So a simply way to do it, it could be to create a property of type NSOperationQueue and add the operation to that queue. When you add it to a queue you don't need to perform start on the operation.

Hope that helps.

Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
  • 1
    the operation MUST be retained somewhere, otherwise it gets deallocated. I would use an operation queue, which is a member of the class. – Felix Jul 08 '12 at 14:36
  • @phix23 Oh yes! he could add that operation within a `NSOperationQueue`. Maybe I can modify my answer to accomodate it. Thanks. – Lorenzo B Jul 08 '12 at 14:38
  • It's will be work but in this way `addObject` to `pointersArray` will be in background thread, instead I want this in main thread. – RomanHouse Jul 08 '12 at 14:42
  • @RomanHouse Why? If the operation is created in the main thread, the completion handler will be performed on that thread. On the contrary, the download mechanism is performed in background thread. You can also check this with `BOOL isMainThread = [NSThread isMainThread]`. – Lorenzo B Jul 08 '12 at 14:52
  • @phix23 I modified my answer based on your comment. Thanks. – Lorenzo B Jul 08 '12 at 14:54