UIImage vom MKMapView

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • UIImage vom MKMapView

    Hi,


    ich quäle mich da grad etwas rum:
    Ich erstelle in meiner iPhone-App unter anderem auch Karten. Davon benötige ich ein png-File.
    Die Karte will ich aber nicht anzeigen lassen. Das soll im Hintergrund passieren.

    Bild erstellen aus der MapView funktioniert. Wird auch gespeichert und ist sogar was drin.

    Nur leider immer unvollständig.




    Sicher hat da schon jemand Erfahrung. An was könnte es liegen?

    Ist das ein Layerproblem? Oder Timing?




    Das Bild erstelle ich so:

    Quellcode

    1. - (void)buildMapImage
    2. {
    3. MKMapView *mapView = self.buildMap;
    4. UIGraphicsBeginImageContext(mapView.frame.size);
    5. [mapView.layer renderInContext:UIGraphicsGetCurrentContext()];
    6. UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    7. UIGraphicsEndImageContext();
    8. // hier wird das Bild gespeichert, das funktioniert
    9. }
    Alles anzeigen





    und hier erstelle ich die Map:




    Quellcode

    1. - (MKMapView *)buildMap
    2. {
    3. MKMapView *mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 250.0f, 250.0f)];
    4. mapView.delegate = self;
    5. mapView.showsUserLocation = YES;
    6. CLLocationCoordinate2D MittelPunktDrivingRange;
    7. MittelPunktDrivingRange.latitude = 51.1614019310332;
    8. MittelPunktDrivingRange.longitude= 6.72118663787842;
    9. // max und min Koordinaten ermitteln damit alle Objekte angezeigt werden
    10. MRAppDelegate *app_min_max = [[UIApplication sharedApplication] delegate];
    11. CLLocationCoordinate2D maxWest = CLLocationCoordinate2DMake(0.0, 999.0);
    12. CLLocationCoordinate2D maxOst = CLLocationCoordinate2DMake(0.0, -999.0);
    13. CLLocationCoordinate2D maxNord = CLLocationCoordinate2DMake(-999.0, 0.0);
    14. CLLocationCoordinate2D maxSued = CLLocationCoordinate2DMake(999.0, 0.0);
    15. for (int i = 0; i < [[app_min_max currentRange] numberOfMarkers]; i++)
    16. {
    17. CLLocation *markerLocation = [[app_min_max currentRange] markerLocationAtIndex:i];
    18. MKPointAnnotation *marker = [[MKPointAnnotation alloc] init];
    19. marker.coordinate = markerLocation.coordinate;
    20. if(marker.coordinate.longitude < maxWest.longitude)
    21. {
    22. maxWest = marker.coordinate;
    23. }
    24. if(marker.coordinate.longitude > maxOst.longitude)
    25. {
    26. maxOst = marker.coordinate;
    27. }
    28. if(marker.coordinate.latitude > maxNord.latitude)
    29. {
    30. maxNord = marker.coordinate;
    31. }
    32. if(marker.coordinate.latitude < maxSued.latitude)
    33. {
    34. maxSued = marker.coordinate;
    35. }
    36. }
    37. CLLocationDegrees midLongitude = (maxWest.longitude + maxOst.longitude)/2.0;
    38. CLLocationDegrees midLatitude = (maxWest.latitude + maxOst.latitude)/2.0;
    39. MittelPunktDrivingRange.longitude = midLongitude;
    40. MittelPunktDrivingRange.latitude= midLatitude;
    41. CLLocation *maxWestMarker = [[CLLocation alloc] initWithLatitude:maxNord.latitude longitude:maxWest.longitude];
    42. CLLocation *maxOstMarker = [[CLLocation alloc] initWithLatitude:maxNord.latitude longitude:maxOst.longitude];
    43. CLLocationDistance breite = [maxWestMarker distanceFromLocation:maxOstMarker];
    44. CLLocation *maxNordMarker = [[CLLocation alloc] initWithLatitude:maxNord.latitude longitude:maxWest.longitude];
    45. CLLocation *maxSuedMarker = [[CLLocation alloc] initWithLatitude:maxSued.latitude longitude:maxOst.longitude];
    46. CLLocationDistance laenge = [maxNordMarker distanceFromLocation:maxSuedMarker];
    47. MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(MittelPunktDrivingRange, breite,laenge);
    48. MKCoordinateRegion adjustedRegion = [mapView regionThatFits:viewRegion];
    49. [mapView setRegion:adjustedRegion animated:YES];
    50. mapView.mapType = MKMapTypeSatellite;
    51. MRAppDelegate *app = [[UIApplication sharedApplication] delegate];
    52. for (int i = 0; i < [[app currentRange] numberOfMarkers]; i++)
    53. {
    54. CLLocation *markerLocation = [[app currentRange] markerLocationAtIndex:i];
    55. NSString *markerName = [[app currentRange] markerNameAtIndex:i];
    56. MKPointAnnotation *marker = [[MKPointAnnotation alloc] init];
    57. marker.coordinate = markerLocation.coordinate;
    58. marker.title = markerName;
    59. [mapView addAnnotation:marker];
    60. }
    61. return (mapView);
    62. }
    Alles anzeigen
    Ich habe auch keine Loesung, aber ich bewundere das Problem!
    _____________________________________________________


  • Die Methode renderInContext: funktioniert anscheinend nicht mit allen Arten von Layern und so kann es in einer Layerhierarchie vorkommen, dass sie einzelne Layer nicht zeichnet. Die genaue Systematik wann das so ist habe ich leider noch nicht herausgefunden. Allerdings kann man vor renderInContext: einfach allen Layern, bis auf die, die ihren Inhalt über contents bereitstellen, ein setNeedsDisplay senden. Das geht relativ einfach über eine rekursive Methode (siehe z. B. Listing 6.45).
    „Meine Komplikation hatte eine Komplikation.“
  • Habe mir das im Buch mal durchgelesen, aber leider bin ich da noch viel zu viel Anfänger um tatsächlich zu verstehen, wo (und vor allem wie) ich jetzt

    Quellcode

    1. - (void)setAllNeedsDisplay { if(self.contents == nil) {
    2. [self setNeedsDisplay];
    3. }
    4. for(id theLayer in self.sublayers) {
    5. [theLayer setAllNeedsDisplay];
    6. }
    7. }

    anzuwenden habe.
    Ich hätte jetzt mal vermutet, dass ich hier eingreifen muss:

    Quellcode

    1. ...MKMapView *mapView = self.buildMap;// hier sollten wohl die layer markiert werden, aber wie?
    2. UIGraphicsBeginImageContext(mapView.frame.size);
    3. [mapView.layer renderInContext:UIGraphicsGetCurrentContext()];
    4. UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    5. UIGraphicsEndImageContext();...
    Ich habe auch keine Loesung, aber ich bewundere das Problem!
    _____________________________________________________


  • Füge die Methode mal in einer Kategorie zu CALayer hinzu und in Dein Listing den entsprechenden Aufruf:

    Quellcode

    1. UIGraphicsBeginImageContext(mapView.frame.size);
    2. [mapView.layer setAllNeedsDisplay];
    3. [mapView.layer renderInContext:UIGraphicsGetCurrentContext()];
    4. UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    5. UIGraphicsEndImageContext();
    „Meine Komplikation hatte eine Komplikation.“
  • macmoonshine schrieb:

    Füge die Methode mal in einer Kategorie zu CALayer hinzu und in Dein Listing den entsprechenden Aufruf:
    Vielen Dank für die Hilfe.
    So habe ich jetzt immerhin auch gleich mal die Kategorie kennen gelernt (Hatte ich bis jetzt noch nie gebraucht (glaube ich)) und Kapitel 2.2.5 durchgearbeitet 8)

    Habe alles genau so eingebaut, hat nur leider nicht geholfen ;(

    So soll es aussehen:

    [IMG:http://www.myrange.de/support/tmp/ganz.png]

    aber leider kommt immer nur das dabei raus
    [IMG:http://www.myrange.de/support/tmp/halb.png]

    ?(
    Ich habe auch keine Loesung, aber ich bewundere das Problem!
    _____________________________________________________


  • So geht's:
    1. Die MKMapView in die View-Hierarchie aufnehmen, z.B. hinter einer Image-View, die das Hintergrundbild zeigt. Das ist notwendig, damit die verschiedenen Layer überhaupt gezeichnet werden. Vielleicht gibt es auch eine Methode, dies selber zu initiieren, ich habe aber keine gefunden.
    2. In der MKMapView-Delegatemethode "mapViewDidFinishLoadingMap" wird mit leichter Verzögerung das renderInContext des View-Layers aufgerufen. Hierzu nutze ich ein "performSelector...". Keine Ahnung, warum diese Verzögerung nötig ist, den eigentlich soll die genannte Methode ja erst aufgerufen werden, wenn alles geladen ist.
    Beides finde ich etwas "fishy", aber immerhin ist die o. g. Kategorie nicht nötig und des Image enthält alle Layer. Bleibt die Frage der Verwendungsrechte...

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.