ApolloX
ApolloX

Reputation: 31

Skobbler didFinishRouteCalculationWithInfo array exception

Getting an exception when using Skobbler Maps in iOS. Seems like a concurrency exception resulting in an invalid array access, but since it's a problem with the provided code from Skobbler, not sure how the best way to fix their broken code.

See the line marked "HERE!!!" in the code below:

File: SKTNavigationManager.m

- (void)routingService:(SKRoutingService *)routingService didFinishRouteCalculationWithInfo:(SKRouteInformation *)routeInformation {
    dispatch_async(dispatch_get_main_queue(), ^{
       __block BOOL routeExists = NO;
       [_calculatedRoutes enumerateObjectsUsingBlock:^(SKRouteInformation *obj, NSUInteger idx, BOOL *stop) {
            if (routeInformation.routeID == obj.routeID) {
                routeExists = YES;
                *stop = YES;
            }
        }];

       if (!routeInformation.corridorIsDownloaded || routeExists || _calculatedRoutes.count == _configuration.numberOfRoutes) {
           return;
       }

       //are we still calculating the routes?
       if ([self hasState:SKTNavigationStateCalculatingRoute]) {
           [_calculatedRoutes addObject:routeInformation];

           //stop progress for the calculated route
           SKTRouteProgressView *progressVIew = _mainView.calculatingRouteView.progressViews[_calculatedRoutes.count - 1]; // HERE!!!
           [progressVIew startProgress];

           //show the info for the calculated route
           [_mainView.calculatingRouteView showInfoViewAtIndex:_calculatedRoutes.count - 1];
           [self updateCalculatedRouteInformationAtIndex:_calculatedRoutes.count - 1];

           //start progress for next route if needed
           if (_calculatedRoutes.count < _mainView.calculatingRouteView.numberOfRoutes) {
               SKTRouteProgressView *progressVIew = _mainView.calculatingRouteView.progressViews[_calculatedRoutes.count];
               [progressVIew startProgress];
           }

           if (!_selectedRoute) {
               _selectedRoute = routeInformation;
               [SKRoutingService sharedInstance].mainRouteId = _selectedRoute.routeID;
               [self zoomOnSelectedRoute];
               _mainView.calculatingRouteView.selectedInfoIndex = 0;
               _mainView.calculatingRouteView.startButton.hidden = NO;
           }
       } else if ([self hasState:SKTNavigationStateRerouting]) { //nope, we're being rerouted
           _selectedRoute = routeInformation;
           _navigationInfo.currentDTA = _selectedRoute.distance;
           [self updateDTA];
           _navigationInfo.currentETA = _selectedRoute.estimatedTime;
           [self updateETA];
           [SKRoutingService sharedInstance].mainRouteId = _selectedRoute.routeID;
           [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(removeReroutingState) object:nil];
           [self performSelector:@selector(removeReroutingState) withObject:nil afterDelay:kMinReroutingDisplayTime];
       }
    });
}

The exception reported is ...

8   libobjc.A.dylib - objc_exception_throw + 332 (objc-exception.mm:568)
9   CoreFoundation - [__NSArrayM objectAtIndex:] + 240 (NSArray.m:410)
10  MyApp -[SKTNavigationManager routingService:didFinishRouteCalculationWithInfo:]_block_invoke + 676 (SKTNavigationManager.m:463)

Any ideas? I could do a check on the size of _calculatedRoutes before reading from the progressViews array, but the problem I have is there is additional code after the line that accesses both. In other words, I can avoid the line, but how do I fix the method to work correctly?

Upvotes: 2

Views: 59

Answers (1)

Ando
Ando

Reputation: 11409

The code inside SKTNavigationManager (and inside the whole SDKTools project) is offered as open code - it is not part of the SDK itself but constitutes some demo code/ helper classes that should help you address common scenarios (building a simple navigation UI, dealing with offline maps, etc.).

Some developers use this code as documentation, others use it "as is" in their projects, others start from it and customize it to their liking.

In you particular case I'm not sure how you did arrive at this inconsistent state (with the vanilla code, in the demo project I cannot replicate this) - if you believe that you have a concurrency issue feel free to insert additional checks or synchronization mechanisms.

Upvotes: 1

Related Questions