If you app is iOS 7+, you have some flexibility by using MKTileOverlay. It allows you to put your own tile set on top of a normal Apple map.
By creating a MKTileOverlay subclass and overload loadTileAtPath:
you could check your bundle for the initial state, then maybe a separate cache for tiles loaded when there was an internet connection, and finally use the URL to load the tile when all else fails.
- (void)loadTileAtPath:(MKTileOverlayPath)path
result:(void (^)(NSData *data, NSError *error))result
{
if (!result) {
return;
}
NSString *filePath = ...; // Predetermined filename based off of MKTileOverlayPath
NSData *initialData = [NSData dataWithContentsOfFile:filePath];
NSData *cachedData = [self.cache objectForKey:[self URLForTilePath:path]];
if (initialData) {
result(initialData, nil);
} else if (cachedData) {
result(cachedData, nil);
} else {
NSURLRequest *request = [NSURLRequest requestWithURL:[self URLForTilePath:path]];
[NSURLConnection sendAsynchronousRequest:request queue:self.operationQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
result(data, connectionError);
}];
}
}
More info and some examples here