7

I'm attempting to build an application that builds and saves routes similar to map my run. I'm using the Breadcrumb sample code, specifically the CrumbPath and CrumbPathView as the base of my routes, from Apple. Two questions:

  1. If I try to access the MKMapPoint *points object of the CrumbPath like so:

    [_route lockForReading];
    NSLog(@"%@", _route.points);
    NSLog(@"%d", _route.pointCount);
    [_route unlockForReading];
    

    my app crashes, saying:

    Thread 1: EXC_BAD_ACCESS (code: 1, address: 0x9450342d)
    

    Which I have a hard time understanding, because within the CrumbPath.m file, the folks at apple write to the "array" by explicitly acquiring the write lock, and then unlocking it, but if I acquire the read lock and attempt to read from it, it crashes.

  2. The reason I attempt to access the points is in an attempt to get the MKMapPoints, convert them to CLLocationCoordinate2D objects, and save them so I can redraw the polyline at the user's request. Since I cannot get access to the points, I attempt to save the CLLocationCoordinate2D objects from my locationManager that I send to the _route in an array to upload to my Parse backend, but I always get an error saying:

    Sending 'CLLocationCoordinate2D' to parameter of incompatible type 'id'
    

    Which isn't making this any easier. Does anybody have any insight to why I'm getting these errors?

Location Manager Delegate

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
    if (_userLocation.longitude != manager.location.coordinate.longitude
        && _userLocation.latitude != manager.location.coordinate.latitude) {
        _userLocation = manager.location.coordinate;
    }

    if (_isRecording) {
        if (!_route) {
            NSLog(@"lat: %f, lng: %f", _userLocation.latitude, _userLocation.longitude);
            _route = [[CrumbPath alloc] initWithCenterCoordinate:_userLocation];
            [_mapView addOverlay:_route];

            MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(_userLocation, 2000, 2000);
            [_mapView setRegion:region animated:YES];
        }else {
            MKMapRect updateRect = [_route addCoordinate:_userLocation];

            if (!MKMapRectIsNull(updateRect)) {
                MKZoomScale currentZoomScale = (CGFloat)(_mapView.bounds.size.width / _mapView.visibleMapRect.size.width);
                CGFloat lineWidth = MKRoadWidthAtZoomScale(currentZoomScale);
                updateRect = MKMapRectInset(updateRect, -lineWidth, -lineWidth);
                [_routeView setNeedsDisplayInMapRect:updateRect];
            }
        }
        [_routePoints addObject:_userLocation];

        [_route lockForReading];
        NSLog(@"%d", _route.pointCount);
        NSLog(@"%@", _route.points);
        [_route unlockForReading];
    }
}

Stop Recording Logic

    //stop recording
    NSLog(@"STOP");
    if (_route) {
        NSLog(@"There is a route");
        //Show route options toolbar
        [_route lockForReading];

        NSLog(@"%@", _route);
        NSLog(@"%d", _route.pointCount);
        NSLog(@"%@", _route.points);

        PFObject *routeToSave = [PFObject objectWithClassName:@"Routes"];
        //[routeToSave setObject:_route forKey:@"routePoints"];

        [_route unlockForReading];

        [routeToSave saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
            if (!error) {
                NSLog(@"%c", succeeded);
            }else {
                NSLog(@"%@", error);
            }
        }];
    }
HighFlyingFantasy
  • 3,789
  • 2
  • 26
  • 38

3 Answers3

10

Regarding your first issue, the crash was because of this:

NSLog(@"%@", _route.pointCount);

It should be:

NSLog(@"%d", _route.pointCount);

As mentioned in my comments, %d should be used for count and %@ will cause a crash.

Regarding your second issue, you cannot add a c struct to an NSArray. You should wrap it in NSValue before adding it to an array. CLLocationCoordinate2D is a c-struct. Check the documentation here.

Change this:

[_routePoints addObject:_userLocation];

to:

NSValue *aValue = [NSValue valueWithMKCoordinate:_userLocation];
[_routePoints addObject:aValue];

To get the coordinate back from NSValue, you can use,

[aValue MKCoordinateValue];

As mentioned in your error message, you were trying to add CLLocationCoordinate2D to an array which expects an object.

iDev
  • 23,310
  • 7
  • 60
  • 85
  • The crash was not caused by the initial `NSLog(@"%@", _route.pointCount);` because the `NSLog(@"%@", _route.points);` line was before it, I reordered it after realizing that it was never getting to the `_route.pointCount` line. But I was ignorant enough to use `%@` before you corrected me. And my `initWithCenterCoordinate:` method says exactly that. – HighFlyingFantasy Jan 14 '13 at 23:07
  • It would have crashed if you used it as shown in question. For second issue, are you sure you are using `(CLLocationCoordinate2D)` and not `(CLLocationCoordinate2D *)`? – iDev Jan 14 '13 at 23:08
  • Yes, I haven't deviated from the Apple sample code. I took the actual files and dropped them in my project, only adding `NSLog()` statements. – HighFlyingFantasy Jan 14 '13 at 23:11
  • @HighFlyingFantasy, Got the issue. Updated the answer with the solution for that. – iDev Jan 14 '13 at 23:19
  • 1
    Much nicer than creating a useless wrapper class. Thank you. – HighFlyingFantasy Jan 14 '13 at 23:32
  • Yup. NSValue itself is a wrapper class and you dont need a new one just for this. Thanks for accepting. Glad to help. – iDev Jan 14 '13 at 23:38
  • [NSValue valueWithMKCoordinate:..] is available from iOS 6 and up – tapmonkey May 25 '13 at 15:27
  • You also need to `#import ` do be able to do this. – matehat Feb 08 '14 at 15:16
1

Whatever api you're using to talk to parse is expecting an id which is a pointer to any object. A cllocationcoordinate2d is a c-struct of two doubles and not an object if I'm not mistaken. You should probably create a little wrapper object to save those two doubles and convert them to/from CLLocationCoordinate2d items.

Cody C
  • 3,087
  • 4
  • 24
  • 32
0

1:

Line: NSLog(@"%@", _route.points); is wrong

_route.points is not a String, and you are using the NSStrig formating symbol "%@".

Further:

Since CLLocationCoordinate2D is a C-Sruct and not an Objective-C Object, you probaly want to create an own GeoPoint class.

AlexWien
  • 28,470
  • 6
  • 53
  • 83