Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Geleitwort
Vorwort
1 Hello iPhone
2 Grundlagen
3 Views und Viewcontroller
4 Alles unter Kontrolle
5 Daten, Tabellen und Controller
6 Models, Layer, Animationen
7 Programmieren, aber sicher
8 Datenserialisierung und Internetzugriff
9 Jahrmarkt der Nützlichkeiten
A Sicherer Entwicklungszyklus
Stichwort

Download:
- ZIP, ca. 49,9 MB
Buch bestellen
Ihre Meinung?

Spacer
Apps programmieren für iPhone und iPad von Klaus M. Rodewig, Clemens Wagner
Das umfassende Handbuch
Buch: Apps programmieren für iPhone und iPad

Apps programmieren für iPhone und iPad
Galileo Computing
1000 S., geb., mit DVD
39,90 Euro, ISBN 978-3-8362-1915-0
Pfeil 8 Datenserialisierung und Internetzugriff
Pfeil 8.1 Ich packe meine Texte
Pfeil 8.1.1 Serialisierung von Zeichenketten
Pfeil 8.1.2 Zeichenkodierungen
Pfeil 8.1.3 Unicode und UTF-8
Pfeil 8.1.4 Die Zeichenkodierung erkennen
Pfeil 8.1.5 Zeichenketten konvertieren
Pfeil 8.2 JSON und die URLonauten
Pfeil 8.2.1 Das JSON-Format
Pfeil 8.2.2 Einfacher YouTube-Zugriff mit JSON
Pfeil 8.2.3 URLs erstellen
Pfeil 8.2.4 JSON-Dokumente schreiben
Pfeil 8.2.5 Verwendung des JSONKits als Parser
Pfeil 8.3 XML
Pfeil 8.3.1 XML in Kürze
Pfeil 8.3.2 Property-Listen
Pfeil 8.3.3 SAX
Pfeil 8.3.4 DOM und XPath
Pfeil 8.3.5 Der Tag der Entscheidung
Pfeil 8.4 Daten, Daten, ihr müsst wandern
Pfeil 8.4.1 Synchrone Kommunikation
Pfeil 8.4.2 Komplexe Anfragen
Pfeil 8.4.3 Auf dem Webserver nichts Neues
Pfeil 8.4.4 Asynchrone Kommunikation
Pfeil 8.4.5 Große Datenmengen der Übertragung
Pfeil 8.4.6 Passwortabfragen
Pfeil 8.4.7 Hier geht die POST ab
Pfeil 8.4.8 Datei-Upload
Pfeil 8.4.9 Überprüfung der Erreichbarkeit
Pfeil 8.5 Karten
Pfeil 8.5.1 Karten darstellen
Pfeil 8.5.2 Koordinatensysteme
Pfeil 8.5.3 Geokoordinaten bestimmen
Pfeil 8.5.4 Eigene Kartenbeschriftungen
Pfeil 8.5.5 Routen

Galileo Computing - Zum Seitenanfang

8.5 KartenZur nächsten Überschrift

Das Beispielprojekt SiteSchedule kann außerdem die Baustellen in einer Karte anzeigen. Dazu verwendet es das MapKit. Dieses Framework erlaubt die Anzeige von Karten mit selbst definierten Anmerkungen. Bis iOS 5 stammte das Kartenmaterial von Google; seit iOS 6 verwendet Apple das Material der Firma TomTom, weswegen die Karten ein anderes Design haben. Ein positiver Effekt dieser Umstellung ist die Aufwertung der Karten-App zu einem vollwertigen Navigationssystem mit gesprochenen Wegbeschreibungen. Außerdem bietet sie für einige Städte eine 3D-Ansicht an. Wenn Sie auf Satelliten- und 3D-Darstellung umschalten, können Sie beispielsweise einen faszinierenden Rundgang durch die Häuserschluchten von New York unternehmen. Die Umstellung erfolgt für die Entwicklung indes vollkommen transparent; das heißt, die APIs sind im Wesentlichen gleich geblieben.


Galileo Computing - Zum Seitenanfang

8.5.1 Karten darstellenZur nächsten ÜberschriftZur vorigen Überschrift

Die Klasse MKMapView erlaubt es Ihnen, Karten in Ihrer App anzuzeigen. Sie brauchen einfach nur einen solchen View in eine Ihrer Viewhierarchien einzubinden, um eine Karte anzuzeigen. Dieser View unterstützt bereits eine Ausschnittauswahl per Scrollen und Zoomen, inklusive der Doppel-Tap-Geste, sowie die Anzeige des aktuellen Standortes.

Abbildung

Abbildung 8.20 Die Einstellungsmöglichkeiten von Karten

Diese Optionen können Sie über den Attributinspektor des Interface Builders einstellen (siehe Abbildung 8.20). Dort können Sie außerdem noch die Darstellungsart auswählen. Hierfür stehen Ihnen unter der Einstellung Type drei Auswahlmöglichkeiten zur Verfügung:

Tabelle 8.17 Die Darstellungsarten des Mapviews

Auswahl Beschreibung

Map

In der Kartendarstellung zeigt der View eine beschriftete Straßenkarte mit Orts- und Straßennamen sowie Sehenswürdigkeiten an.

Satellite

Die Satellitenansicht stellt das Gelände als Satellitenaufnahme ohne Standardbeschriftungen dar.

Hybrid

Die Hybriddarstellung zeigt die Satellitenansicht mit den Beschriftungen und Wegen aus der Kartendarstellung an.

Über die Property mapType können Sie die Darstellungsart auch aus Ihrem Programmcode heraus verändern. In Abbildung 8.21 sehen Sie den gleichen Kartenausschnitt in den drei unterschiedlichen Darstellungsarten.

Abbildung

Abbildung 8.21 Die Darstellungsarten des Mapviews

Wie bereits erwähnt wurde, kann der Mapview auch die aktuelle Position des Gerätes auf der Karte anzeigen. Da das allerdings eine sensible Information ist, fragt iOS den Nutzer für jede App über ein Alert nach, ob die App seinen aktuellen Standort verwenden darf. Die Anzeige des Standortes erfolgt dabei über einen blauen Punkt, der gegebenenfalls in einem hellblauen, transparenten Kreis mit dunkelblauem Rand liegt. Dieser Kreis gibt die Genauigkeit der Standortbestimmung an. Der hellblaue Ring um den aktuellen Standort (siehe Abbildung 8.22) dient hingegen lediglich zur Hervorhebung. Wenn iOS den Gerätestandort bestimmt, zeigt das die Statusleiste links neben dem Batteriesymbol durch eine Kompassnadel an. Der Mapview aktualisiert den Gerätestandort automatisch. Wenn sich der Nutzer also mit dem iPhone weit genug fortbewegt, ändert auch der blaue Punkt seine Position auf der Karte.

Abbildung

Abbildung 8.22 Anzeige des aktuellen Standortes


Galileo Computing - Zum Seitenanfang

8.5.2 KoordinatensystemeZur nächsten ÜberschriftZur vorigen Überschrift

Die Klasse MKMapView ist eine Unterklasse von UIView und basiert somit auf dem Koordinatensystem von Cocoa Touch, das jedoch für Karten sehr unpraktisch ist. Um einen Punkt auf der Erdoberfläche anzugeben, verwendet man geografische Koordinaten, die aus einer Breiten- und einer Längengradangabe bestehen. [http://de.wikipedia.org/wiki/Geographische_Koordinaten] Dabei sind beide Werte Winkelangaben, deren Nulllinie der Äquator beziehungsweise der Nullmeridian ist. Der Nullmeridian ist dabei ein festgelegter Kreis um die Erde, der sowohl durch den Nord- und den Südpol als auch durch den Mittelpunkt des Teleskops des Königlichen Observatoriums von Greenwich, London, verläuft.

In Cocoa Touch können Sie diese Koordinaten durch eine Variable der Struktur CLLocationCoordinate2D darstellen, die die beiden Felder latitude und longitude für Breiten- und Längengrad bereitstellt. Die Angaben dieser Winkel erfolgen immer im Gradmaß. Beispielsweise hat der Kölner Dom die geografischen Koordinaten (50,941302°; 6,957189°). [Die Angabe einer Koordinate erfolgt immer in (Breitengrad; Längengrad).]

Die Struktur MKCoordinateRegion dient zur Beschreibung eines Bereichs auf der Erdkugel, in dem eine geografische Koordinate den Mittelpunkt darstellt und zwei Winkel die Breiten- und Längenabweichung vom Mittelpunkt darstellen. Diese Abweichungen beschreibt die Struktur MKCoordinateSpan. Der Bereich ähnelt bei der Draufsicht in den meisten Fällen einem Trapez, wie Abbildung 8.23 eins darstellt. Dabei entspricht der Schnittpunkt der gestrichelten Linien dem Mittelpunkt.

Abbildung

Abbildung 8.23 Ein Bereich auf der Kugeloberfläche

Über geografische Koordinaten können Sie den angezeigten Kartenausschnitt eines Mapviews festlegen. Über die Property centerCoordinate können Sie beispielsweise den Mittelpunkt auslesen und ändern, und über setCenterCoordinate:animated: können Sie die Änderung auch mit einer Animation durchführen.

Über die Property region können Sie den Bereich auslesen und ändern. Dabei verwenden Sie jeweils Werte der besprochenen Struktur MKCoordinateRegion. Diese Property erlaubt Ihnen also die gleichzeitige Wahl des Mittelpunktes und der Skalierung der Karte. Über setRegion:animated: können Sie auch diese Änderung animieren lassen.

Über Geokoordinaten lassen sich aufgrund der Erdkrümmung nur sehr schlecht rechteckige Kartenausschnitte beschreiben. Dafür gibt es die Struktur MKMapRect, die ein Rechteck auf der projizierten Karte darstellt. Für diese Struktur stellt das MapKit verschiedene geometrische Funktionen bereit. Die Definition eines Kartenrechtecks über diese Struktur erfolgen analog zu CGRect über einen Ursprung und die Größe.

Das Beispielprojekt SiteSchedule bestimmt zu jeder Baustelle die geografischen Koordinaten und berechnet aus allen Koordinaten in der Property mapRect das kleinstmögliche Rechteck für die Anzeige. Dazu verwendet es die Funktion MKMapRectUnion, die das kleinste Rechteck berechnet, in dem die zwei übergebenen Rechtecke liegen.

- (void)updateMapRectWithCoordinate:Zeilenumbruch
(CLLocationCoordinate2D)inCoordinate Zeilenumbruch
isFirst:(BOOL)inIsFirst {
MKMapPoint thePoint = Zeilenumbruch
MKMapPointForCoordinate(inCoordinate);
MKMapRect theRect = MKMapRectNull;

theRect.origin = thePoint;
self.mapRect = inIsFirst ? theRect : Zeilenumbruch
MKMapRectUnion(self.mapRect, theRect);
}

Listing 8.76 Berechnung des kleinsten Rechtecks

Die Methode updateMapRectWithCoordinate:isFirst: aus Listing 8.76 wandelt dazu zunächst die übergebene Koordinate über die Funktion MKMapPointForCoordinate in einen Punkt um. Diesen Punkt dient als Ursprung für ein Rechteck mit der Breite und der Höhe 0. Wenn es sich um die erste Koordinate in der Berechnung handelt, ist dieses Rechteck das Ergebnis der Berechnung, ansonsten berechnet die Methode die Vereinigung aus dem vorherigen Ergebnis mit dem neuen Rechteck. Nachdem die App alle Koordinaten eingerechnet hat, legt sie über die Methode setVisibleRect:animated: den Ausschnitt des Mapviews fest.


Galileo Computing - Zum Seitenanfang

8.5.3 Geokoordinaten bestimmenZur nächsten ÜberschriftZur vorigen Überschrift

Sowohl für die Berechnung des Kartenausschnitts als auch für die Anzeige der Baustellen auf der Karte muss die App die Geokoordinaten der Baustellen kennen. Dafür können Sie die Klasse CLGeocoder aus dem CoreLocation-Framework verwenden. Diese Klasse gibt es seit iOS 5, und sie unterstützt sowohl die Berechnung von Geokoordinaten aus Adressen als auch die Umkehrung, bei der sie zu einer Koordinate eine Adresse bestimmt. Der Geocoder benötigt allerdings immer eine Internetverbindung, um Geokoordinaten oder Adressen zu bestimmen.

Er kann dabei die Geokoordinaten sowohl aus einem Dictionary mit den einzelnen Bestandteilen der Adresse als auch aus einer Zeichenkette bestimmen. Das Beispielprojekt SiteSchedule verwendet die erste Variante, da ja die Adressen der Baustellen schon fein säuberlich in Straße, Postleitzahl, Stadt und Land aufgeteilt vorliegen. Die Methode address der Klasse Site liefert die enthaltene Adresse als Dictionary für die Geokodierung:

- (NSDictionary *)address {
return [NSDictionary dictionaryWithObjectsAndKeys:
self.zip, kABPersonAddressZIPKey,
self.city, kABPersonAddressCityKey,
self.countryCode, kABPersonAddressCountryCodeKey,
self.street, kABPersonAddressStreetKey,
nil];
}

Listing 8.77 Erstellung des Adress-Dictionarys für die Geokodierung

Die Schlüssel für das Dictionary stellt dabei das AddressBook-Framework bereit, und das Beispielprojekt bindet dieses Framework nur für diese Konstanten ein.

Sie dürfen zwar beliebig viele Geocoder-Objekte in einer App anlegen, allerdings sollten Sie niemals mehrere Anfragen gleichzeitig stellen. Da die Geokodierungsanfragen asynchron erfolgen, können Sie bei mehreren Anfragen also nicht einfach eine Schleife schreiben, die mehrere Anfragen direkt nacheinander abschickt.

Die Klasse MapViewController umgeht dieses Problem durch rekursive Aufrufe, indem sie eine Anfrage startet und die nächste Anfrage erst nach deren Ende stellt. Dazu verwendet sie die Property sites, die alle Baustellen enthält. Der Controller ermittelt jedoch die Koordinaten einer Baustelle nur, wenn sie noch keine hat, und speichert die ermittelten Koordinaten einer Baustelle in deren Core-Data-Entität ab. Die Methode updateGeocoordinates: erhält als Parameter den Index der Baustelle, die sie als Nächstes verarbeiten soll. Sie ist dabei in drei Teile unterteilt. Die erste While-Schleife wertet die Baustellen ab dem Index aus, die bereits eine Geokoordinate haben. Dabei fügt sie deren Koordinate zum Kartenrechteck hinzu (siehe Listing 8.76) und kennzeichnet sie auf der Karte mit einem Pin. Wenn nach dem Durchlauf dieser Schleife die Variable theSite gleich nil ist, wurden alle Baustellen lokalisiert. Andernfalls hat die Schleife eine Baustelle ohne Geokoordinaten gefunden, und die Methode startet eine Lokalisierungsanfrage mit der Adresse der Baustelle.

- (void)updateGeocoordinates:(NSUInteger)inIndex {
NSUInteger theIndex = inIndex;
Site *theSite = nil;

while(theIndex < self.sites.count) {
theSite = [self.sites objectAtIndex:theIndex];
if(theSite.hasCoordinates) {
[self updateMapRectWithCoordinate:Zeilenumbruch
theSite.coordinate isFirst:theIndex == 0];
[self addAnntationForSite:theSite];
theIndex++;
theSite = nil;
}
else {
break;
}
}
if(theSite != nil) {
[self.geocoder geocodeAddressDictionary:
theSite.address completionHandler:Zeilenumbruch
^(NSArray *inPlacemarks, NSError *inError) {
if(inError == nil && inPlacemarks.count > 0) {
CLPlacemark *thePlacemark = Zeilenumbruch
[inPlacemarks objectAtIndex:0];
CLLocationCoordinate2D theCoordinate = Zeilenumbruch
thePlacemark.location.coordinate;

theSite.coordinate = theCoordinate;
[self updateMapRectWithCoordinate:Zeilenumbruch
theCoordinate isFirst:inIndex == 0];
[self addAnntationForSite:theSite];
}
else {
NSLog(@"error = %@", inError);
}
[self updateGeocoordinates:theIndex + 1];
}];
}
if(theIndex >= self.sites.count) {
[self.mapView setVisibleMapRect:self.mapRect Zeilenumbruch
animated:YES];
[self.managedObjectContext save:NULL];
}
}

Listing 8.78 Aktualisierung der Geokoordinaten

Dazu verwendet sie die Methode geocodeAddressDictionary:completionHandler: des Geocoders. Die Blockfunktion, die das Ergebnis der Anfrage auswertet, erhält ein Array mit Objekten der Klasse CLPlacemark, wovon sie jedoch nur das erste Element verwendet. Geokodierungsanfragen müssen kein eindeutiges Ergebnis liefern, da Sie ja nicht unbedingt alle Details einer Adressanfrage angeben müssen. In der Regel sollte dieses Array allerdings nur ein Element enthalten.

Am Ende ruft die Blockfunktion erneut die Methode updateGeocoordinates: auf. Da der Indexwert bei dem erneuten Aufruf gegenüber dem aktuellen Aufruf jedoch immer höher ist, muss diese Rekursion enden, da irgendwann das komplette Array durchlaufen wurde. In diesem Fall setzt die Methode das sichtbare Rechteck des Mapviews und speichert die geänderten Koordinaten in der Datenhaltung.


Galileo Computing - Zum Seitenanfang

8.5.4 Eigene KartenbeschriftungenZur nächsten ÜberschriftZur vorigen Überschrift

Die Anzeige einer Karte ist in den meisten Fällen nur dann sinnvoll, wenn die App sie mit eigenen Daten anreichert. Sie können dafür zu einem Mapview Anmerkungen hinzufügen. Für solche Anmerkungen können Sie beliebige Objekte verwenden, sofern sie das Protokoll MKAnnotation implementieren. Dabei muss eine Implementierung allerdings nur die Methode coordinate zwingend bereitstellen, da sie die Position der Anmerkung auf der Karte als Geokoordinate angibt.

Das Beispielprojekt verwendet eine eigene Klasse namens Annotation für die Anmerkungen, die alle Methoden des Protokolls über die drei Propertys coordinate, title und subtitle implementiert. In der Property objectId speichert sie außerdem noch die Kennung der Site-Entität, zu der die Anmerkung gehört.

Die Klasse MKMapView stellt die vier Methoden addAnnotation:, addAnnotations:, removeAnnotation: und removeAnnotations: bereit, mit denen Sie die Anmerkungen einer Karte verwalten können. Außerdem können Sie über die Read-Only-Property annotations alle Anmerkungen der Karte erfragen.

Der Mapview erzeugt für jede Anmerkung, die im sichtbaren Teil der Karte liegt, einen View zur Darstellung. Die Klasse des Views muss dabei eine Unterklasse von MKAnnotationView sein. Die Erzeugung der Views erfolgt über die Delegate-Methode mapView:viewForAnnotation:, deren Implementierung sehr ähnlich zu der Methode tableView:cellForRowAtIndexPath: der Datenquelle eines Tableviews ist.

Abbildung

Abbildung 8.24 Karte mit Anmerkungen

Für die Anzeige der Anmerkungen verwendet das Beispielprojekt Views der Klasse MKPinAnnotationView, die an der Koordinate der Anmerkung eine Stecknadel anzeigen. Wenn Sie die Nadel antippen, erscheint darüber eine Sprechblase mit dem Titel, dem Untertitel und gegebenenfalls einem Bild. Außerdem können Sie noch auf der linken und rechten Seite jeweils einen View anzeigen lassen. Das Beispielprojekt verwendet hierzu zwei Buttons (siehe Abbildung 8.24).

- (MKAnnotationView *)mapView:(MKMapView *)inMapView Zeilenumbruch
viewForAnnotation:(id<MKAnnotation>)inAnnotation {
MKPinAnnotationView *theView = nil;

if(![inAnnotation isKindOfClass:[MKUserLocation class]]) {
theView = (MKPinAnnotationView *)[inMapView Zeilenumbruch
dequeueReusableAnnotationViewWithIdentifier:
@"Site"];
if(theView == nil) {
UIButton *theLeftButton = [UIButton Zeilenumbruch
buttonWithType:UIButtonTypeInfoLight];
UIButton *theRightButton = [UIButton Zeilenumbruch
buttonWithType:UIButtonTypeDetailDisclosure];

theLeftButton.tag = 10;
theRightButton.tag = 20;
theView = [[MKPinAnnotationView alloc] Zeilenumbruch
initWithAnnotation:inAnnotation Zeilenumbruch
reuseIdentifier:@"Site"];
theView.pinColor = MKPinAnnotationColorRed;
theView.canShowCallout = YES;
theView.animatesDrop = YES;
theView.leftCalloutAccessoryView = Zeilenumbruch
theLeftButton;
theView.rightCalloutAccessoryView = Zeilenumbruch
theRightButton;
}
else {
theView.annotation = inAnnotation;
}
}
return theView;
}

Listing 8.79 Erzeugung der Views für die Anmerkungen

Bei der Erzeugung der Views müssen Sie noch einen Sonderfall berücksichtigen: Wenn die Karte den aktuellen Standort anzeigt, dann ruft der Mapview die Delegate-Methode mit einer Anmerkung der Klasse MKUserLocation zu dieser Koordinate auf. Sie können nun entweder einen View für den Nutzerstandort erzeugen oder einfach nil zurückgeben und so die Standardansicht, einen blauen Tropfen, anzeigen.

Für alle anderen Anmerkungen verwendet das Delegate, wie bereits erwähnt, PinAnnotationViews. Die erzeugt es entweder neu, oder es verwendet einen bereits erzeugten, allerdings wieder freigegebenen View. Nach der Erzeugung initialisiert die Methode aus Listing 8.79 noch den linken und rechten Accessoryview mit jeweils einem Button. Außerdem setzt sie canShowCallout auf YES, damit der Pin auch die Sprechblase nach dem Antippen anzeigt. Das Setzen der Property animatesDrop auf YES bewirkt, dass der Mapview die Anzeige des Pins animiert.

Der linke Button in der Sprechblase zeigt einen Viewcontroller mit Informationen zu der Baustelle an, während der rechte Button zur Anzeige von Routen zu der Baustelle dient. Sie können für diese Aktionen entweder – wie bei jedem anderen Button auch – Actionmethoden konfigurieren oder die Delegate-Methode mapView:annotationView:calloutAccessoryControlTapped: verwenden. Der Vorteil der Delegate-Methode ist, dass diese Ihnen die Anmerkung mitliefert. Sie funktioniert allerdings nur, wenn der entsprechende Accesoryview eine Unterklasse von UIControl hat. Die Implementierung dieser Delegate-Methode in Listing 8.80 unterscheidet die beiden Buttons anhand ihres Tagwertes voneinander.

- (void)mapView:(MKMapView *)mapView Zeilenumbruch
annotationView:(MKAnnotationView *)inView Zeilenumbruch
calloutAccessoryControlTapped:(UIControl *)inControl {
Annotation *theAnnotation = inView.annotation;
Site *theSite = (Site *)[self.managedObjectContext Zeilenumbruch
objectWithID:theAnnotation.objectId];

if(inControl.tag == 10) {
ActivitiesViewController *theController = Zeilenumbruch
[self.storyboard Zeilenumbruch
instantiateViewControllerWithIdentifier:Zeilenumbruch
@"activities"];

[theController setUnorderedActivities:Zeilenumbruch
theSite.activities];
[self.navigationController Zeilenumbruch
pushViewController:theController animated:YES];
}
// Ansonsten Route anzeigen...
}

Listing 8.80 Ausführung der Aktion für den linken Accessoryview

Da die Delegate-Methode die Anmerkung als Parameter erhält, kann sie über deren Property objectId das zugehörige Site-Objekt aus Core-Data laden und damit den Viewcontroller für die Anzeige der Aktivitäten konfigurieren.


Galileo Computing - Zum Seitenanfang

8.5.5 RoutenZur nächsten ÜberschriftZur vorigen Überschrift

Über den rechten Button in der Sprechblase kann sich der Nutzer Routen von seinem aktuellen Standardort zu der Baustelle anzeigen lassen. Diese Anzeige geschieht allerdings nicht in der App, sondern in der App Karten, die zu iOS gehört. In den Versionen vor iOS 6 mussten Sie die Karten-App über eine URL aufrufen. Seit iOS 6 stellt Apple mit der Klasse MKMapItem dafür eine komfortablere Zugriffsmöglichkeit bereit.

Zugriff auf die Maps-App unter iOS 6

Sie können unter iOS 6 die Karten-App aus Ihrem Programm heraus über die Klasse MKMapItem öffnen. Dabei stellen die Objekte dieser Klasse die Standorte auf der Karte dar, die Sie in der Karten-App darstellen wollen. Ein Mapitem basiert dabei entweder auf dem aktuellen Standort oder einer Ortsmarke, das sind Objekte der Klasse MKPlacemark. Diese Objekte können neben der Geokoordinate noch eine Reihe weiterer Informationen speichern, wie die Adresse oder die Höhe über dem Meeresspiegel.

Über den Convenience-Konstruktor mapItemForCurrentLocation können Sie ein Mapitem zum aktuellen Standort erzeugen, das keine konkreten Koordinaten enthält. Es dient der Karten-App zur Identifizierung des Gerätestandortes, und die Position seiner Markierung auf der Karte passt sich automatisch an, wenn sich der Standort des Gerätes weit genug ändert. Im Gegensatz dazu haben alle Mapitems mit einer Ortsmarke eine feste Position auf der Karte. Sie können diese Objekte nur über den Initializer initWithPlacemark: konfigurieren und einmal erzeugte Objekte danach nicht mehr verändern.

Für die Erzeugung einer Ortsmarke benötigen Sie eine Geokoordinate und ein Dictionary mit den Adressdaten. Da die Ortsmarke für das Dictionary ebenfalls die Schlüssel aus dem AddressBook-Framework verwendet, nutzt das Beispielprojekt die Methode address der Klasse Site, die Sie bereits kennengelernt haben. Zusätzlich zu den Adressdaten kann ein Mapitem auch eine URL und einen Namen speichern. Mit folgendem Code können Sie beispielsweise ein Mapitem zu einer Baustelle anlegen:

MKPlacemark *thePlacemark = [[MKPlacemark alloc] Zeilenumbruch
initWithCoordinate:theSite.coordinate Zeilenumbruch
addressDictionary:theSite.address];
MKMapItem *theItem = [[MKMapItem alloc] Zeilenumbruch
initWithPlacemark:thePlacemark];

theItem.name = theSite.name;

Listing 8.81 Erzeugung eines Mapitems zu einer Baustelle

Die Methode openInMapsWithLaunchOptions: der Klasse MKMapItem ermöglicht es Ihnen, diesen Eintrag in der Karten-App anzeigen zu lassen. Sie können für die Optionen einfach nil angeben; dann zeigt die Karten-App das Mapitem einfach nur an. Da jedoch bereits die SiteSchedule-App einen entsprechenden Eintrag auf ihrer Karte anzeigt, haben Sie damit noch nicht viel gewonnen. Durch die Optionen aus Tabelle 8.18 können Sie indes die Darstellung der Karten-App beeinflussen.

Tabelle 8.18 Aufrufoptionen für die Karten-App

Schlüssel (Wert) Beschreibung

MKLaunchOptionsDirectionsModeKey

(MKLaunchOptionsDirections-Mode Driving oder -Walking)

Stellt Routen zwischen den Mapitems dar. Wenn der Aufruf nur ein Element enthält, startet die Route beim aktuellen Standort.

MKLaunchOptionsMapTypeKey

(MKMapType)

Die Art der Kartendarstellung. Um diesen Wert in das Dictionary einfügen zu können, müssen Sie ihn in ein NSNumber-Objekt verpacken.

MKLaunchOptionsMapCenterKey

(MKCoordinate)

Legt den Mittelpunkt der Karte fest. Den Wert müssen Sie über die Klassenmethode valueWithMKCoordinate in ein NSValue-Objekt kapseln.

MKLaunchOptionsMapSpanKey

(MKCoordinateSpan)

Enthält die Größe der angezeigten Karte. Den Wert müssen Sie über die Klassenmethode valueWithMKCoordinateSpan in ein NSValue-Objekt kapseln.

MKLaunchOptionsShowsTrafficKey

(NSNumber)

Blendet für den Wert YES Verkehrsinformationen ein.

Sie brauchen in den Optionen natürlich nur die von Ihnen benötigten Einträge zu setzen; für die nicht gesetzten Werte verwendet die App automatisch sinnvolle Einstellungen. Die SiteSchedule-App öffnet beim Antippen des rechten Buttons in der Sprechblase aus Abbildung 8.24 den in Listing 8.81 erzeugten Eintrag folgendermaßen:

[theItem openInMapsWithLaunchOptions:@{
MKLaunchOptionsDirectionsModeKey :
MKLaunchOptionsDirectionsModeDriving,
MKLaunchOptionsShowsTrafficKey : @YES }];

Listing 8.82 Anzeige eines Eintrags in der Karten-App

Die Karten-App zeigt also durch diese Optionen auch mögliche Routen vom aktuellen Standort zu der Baustelle und die verfügbaren Verkehrsinformationen an.

Mit der Klassenmethode openMapsWithItems:launchOptions: können Sie mehrere Mapitems in der Karten-App anzeigen lassen, die Sie im ersten Parameter in einem Array übergeben. Für die Optionen können Sie die gleichen Schlüssel-Wert-Paare wie bei der Methode openInMapsWithLaunchOptions: verwenden. Dabei dürfen Sie die Option MKLaunchOptionsDirectionsModeKey indes nur verwenden, wenn das Array höchstens zwei Einträge enthält. Die Karten-App zeigt bei genau zwei Mapitems mögliche Routen von dem ersten zu dem zweiten Mapitem an.

Wenn die Methoden openInMapsWithLaunchOptions: beziehungsweise openMapsWithItems:launchOptions: die Karten-App jeweils nicht öffnen konnten, liefern sie als Ergebnis NO.

Start der Maps-App über eine URL

Unter den iOS-Versionen vor 6 konnten Sie die Karten-App nur über eine URL öffnen, die einer offiziellen Google-Maps-URL entspricht. Dabei lautet die Basis-URL http://www.libxml.org?. An diese Basis-URL müssen Sie noch die Parameter für die Konfiguration der Karte anhängen.

Tabelle 8.19 URL-Parameter für Google-Maps

Parameter Bemerkungen

q

Enthält einen Suchbegriff für eine Adresse, wie Sie ihn von der
Google-Maps-Webseite kennen.

ll

Legt den Mittelpunkt der Karte in Geokoordinaten fest.

spn

Legt den Bereich der Karte um den Mittelpunkt fest.

t

Enthält die Art der Kartendarstellung. Mögliche Werte: roadmap,
satellite
, hybrid und terrain.

z

Der Vergrößerungsfaktor

saddr

Bei der Anzeige von Routen enthält dieser Parameter die Startadresse.

daddr

Bei der Anzeige von Routen enthält dieser Parameter die Zieladresse.

Geokoordinaten geben Sie in den Parametern mit Dezimalpunkt und durch ein Komma getrennt an. Wenn Sie die URL konstruiert haben, starten Sie damit die Karten-App, indem Sie die URL als Parameter an die Methode openURL: des Application-Singletons übergeben. Wenn Sie beispielsweise eine Karte mit dem Kölner Dom im Zentrum anzeigen möchten, können Sie das folgendermaßen machen:

NSURL *theURL = [NSURL URLWithString:Zeilenumbruch
@"http://maps.google.de/maps?q=50.941302,6.957189"];
UIApplication *theApplication = Zeilenumbruch
[UIApplication sharedApplication];

[theApplication openURL:theURL];

Listing 8.83 Anzeigen eines Standortes in der Google-Karten-App

Wenn Sie eine Route anzeigen möchten, müssen Sie die Parameter saddr und daddr in der URL mit den Geokoordinaten des Start- und des Zielpunktes angeben.

Tipp

Wenn Sie die URL dynamisch erstellen möchten, sollten Sie die Parameterwerte mit der Kategoriemethode encodedStringForURLWithEncoding: aus Listing 8.8 maskieren.

Falls Ihre App sowohl iOS 5 als auch iOS 6 unterstützen soll, ist es sinnvoll, die Verfügbarkeit der Klasse MKMapItem zu überprüfen, um den richtigen Weg für die Anzeige der Karten-App herauszufinden. Für den Test nutzen Sie die Funktion NSClassFromString, die nil liefert, wenn die angegebene Klasse nicht existiert. Damit können Sie nun den fehlenden else-Teil für Listing 8.80 implementieren:

else if(NSClassFromString(@"MKMapItem") == nil) {
CLLocationCoordinate2D theCoordinate = Zeilenumbruch
theSite.coordinate;
NSString *theQuery = [NSString Zeilenumbruch
stringWithFormat:@"%f,%f", Zeilenumbruch
theCoordinate.latitude, theCoordinate.longitude];
NSString *theString = [NSString Zeilenumbruch
stringWithFormat:@"http://maps.google.de/maps?q=%@", Zeilenumbruch
[theQuery encodedStringForURLWithEncoding:Zeilenumbruch
NSUTF8StringEncoding]];
NSURL *theURL = [NSURL URLWithString:theString];
UIApplication *theApplication = Zeilenumbruch
[UIApplication sharedApplication];

[theApplication openURL:theURL];
}
else {
MKPlacemark *thePlacemark = [[MKPlacemark alloc] Zeilenumbruch
initWithCoordinate:theSite.coordinate Zeilenumbruch
addressDictionary:theSite.address];
MKMapItem *theItem = [[MKMapItem alloc] Zeilenumbruch
initWithPlacemark:thePlacemark];

theItem.name = theSite.name;
[theItem openInMapsWithLaunchOptions:@{
MKLaunchOptionsDirectionsModeKey : Zeilenumbruch
MKLaunchOptionsDirectionsModeDriving,
MKLaunchOptionsShowsTrafficKey : @YES }];
}

Listing 8.84 Anzeige einer Route in der Karten-App

Listing 8.84 verwendet unter iOS 5 eine URL und unter iOS 6 ein Mapitem zum Öffnen der Karten-App.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.







<< zurück
  Zum Katalog
Zum Katalog: Apps programmieren für iPhone und iPad

Apps programmieren für iPhone und iPad
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Einstieg in Objective-C 2.0 und Cocoa





 Einstieg in
 Objective-C 2.0
 und Cocoa


Zum Katalog: Apps entwickeln für iPhone und iPad - Videotraining






 Apps entwickeln für
 iPhone und iPad -
 Videotraining


Zum Katalog: Apps mit HTML5 und CSS3






 Apps mit HTML5
 und CSS3


Zum Katalog: iPhone- und iPad-Apps entwickeln






 iPhone- und
 iPad-Apps entwickeln


Zum Katalog: Android 4






 Android 4


Zum Katalog: Android-Apps entwickeln - Videotraining






 Android-Apps
 entwickeln -
 Videotraining


Zum Katalog: Windows Store Apps mit XAML und C#






 Windows Store Apps
 mit XAML und C#


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo





Copyright © Galileo Press 2013
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de