2016-08-09 56 views
17

Mam dużą potrzebę zrobienia mapy offline dla mojej aplikacji, ponieważ jest ona wykonana głównie w Tajlandii, gdzie często trudno jest uzyskać połączenie z Internetem. Używam teraz OpenStreetMap dla mojego MKTileOverlay, ale mam problemy z zaimplementowaniem go do użytku w trybie offline. Znalazłem samouczek, który mówi do podklasy MKTileOverlay. Tak więc, moim ViewController gdzie mapa jest mam:Offline Cache of Map

- (void)viewWillAppear:(BOOL)animated { 

    CLLocationCoordinate2D coord = {.latitude = 15.8700320, .longitude = 100.9925410}; 
    MKCoordinateSpan span = {.latitudeDelta = 3, .longitudeDelta = 3}; 
    MKCoordinateRegion region = {coord, span}; 
    [mapView setRegion:region]; 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    self.title = @"Map"; 
    NSString *template = @"http://tile.openstreetmap.org/{z}/{x}/{y}.png"; 
    self.overlay = [[XXTileOverlay alloc] initWithURLTemplate:template]; 
    self.overlay.canReplaceMapContent = YES; 
    [mapView addOverlay:self.overlay level:MKOverlayLevelAboveLabels]; 
} 

- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id)overlay { 

    return [[MKTileOverlayRenderer alloc] initWithTileOverlay:overlay]; 
} 

W moim podklasy MKTileOverlay, mam:

- (NSURL *)URLForTilePath:(MKTileOverlayPath)path { 
    return [NSURL URLWithString:[NSString stringWithFormat:@"http://tile.openstreetmap.org/{%ld}/{%ld}/{%ld}.png", (long)path.z, (long)path.x, (long)path.y]]; 
} 

- (void)loadTileAtPath:(MKTileOverlayPath)path 
       result:(void (^)(NSData *data, NSError *error))result 
{ 
    if (!result) { 
     return; 
    } 
    NSData *cachedData = [self.cache objectForKey:[self URLForTilePath:path]]; 
    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); 
     }]; 
    } 
} 

Problem jest, że nic nie zostanie załadowany w ogóle, chyba że zakomentuj kod w podklasie. Gdzie ja się mylę?

+0

Gdzie wywołujesz metodę loadTileAtPath? – ldindu

+0

Nie nazywam tego, ponieważ nie jestem pewien JAK to wywołać, ponieważ wymaga ścieżki i nie wiem jak to uzyskać. @ oldindu – user717452

+0

@ oldindu Jak mam przekazać ścieżkę do miejsca, w którym mapa początkowo do niego ładuje? Z normalnym initWithUrlTemplate tak się dzieje, ale po prostu nie mam pojęcia o tej konfiguracji. – user717452

Odpowiedz

1

W naszej firmie zdecydowaliśmy się użyć MapBox do naszego mapowania offline.

Tam można zaprojektować i ułożyć własne mapy za pomocą MapBox Studio, a następnie wyeksportować mapy (w wybranym zakresie poziomów powiększenia) do zewnętrznego pliku. Nasz ma około 40 MB.

Stamtąd można użyć numeru MapBox iOS SDK, aby łatwo dodać go do swojej aplikacji.

(Nota prawna: nie, nie dla nich pracuję!) Wybraliśmy je specjalnie do definiowania własnych kolorów i stylów lądowych/morskich, a także możliwość włączenia plików map do naszego projektu Xcode, oraz użyteczny offline.)

Doceniam twoje dokładne pytanie było jak uzyskać, aby własne mapy OpenStreetMap były offline, ale mam nadzieję, że to ci się przyda.

1

Wygląda na to, że nie wypełniasz pamięci podręcznej. Zawsze będzie puste?

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) { 

     // Instantiate a new cache if we don't already have one. 
     if (!self.cache) self.cache = [NSCache new]; 

     // Add the data into the cache so it's there for next time. 
     if (data) { 
      [self.cache setObject:data forKey:[self URLForTilePath:path]]; 
     } 

     result(data, connectionError); 
    }]; 
} 

Myślę, że to rozwiąże twój problem tutaj. Pamiętaj, że NSCache nie utrzymuje się na dysku (tylko w pamięci), więc dopóki nie przeżyje aplikacji będącej w tle, będziesz potrzebował czegoś bardziej złożonego na dłuższą metę, jeśli chcesz mieć całkowitą możliwość pracy w trybie offline (prawdopodobnie Core Data).