Question

New to monotouch aka xamarin ios. Trying to get a robust mapkit working that can take a number of pins. Experimenting with a basic example that I've cobbled together from a variety of sources that I could find.

Getting a sporadic SIGSEGV error. Seems like some sort of memory error when the pins are clicked to show an alert box which sometimes works and sometimes doesnt.

I'm not sure where I'm going wrong. Is this along the right lines? Here's the code

    using System;
    using System.Drawing;

    using MonoTouch.Foundation;
    using MonoTouch.UIKit;
    using MonoTouch.MapKit;
    using MonoTouch.CoreLocation;
    using System.Collections.Generic;

    namespace singleview
    {
    public partial class singleviewViewController : UIViewController
    {
        public singleviewViewController () : base ("singleviewViewController", null)
        {

        }

        private LocationService locationService;
        private MKMapView mapView;

        List<BasicMapAnnotation> pins = new List<BasicMapAnnotation>();

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            // example of a series of map points
            pins.Add(new BasicMapAnnotation(new CLLocationCoordinate2D(37.766995, -122.419580), "h", "sub1", "id1"));
            pins.Add(new BasicMapAnnotation(new CLLocationCoordinate2D(37.776880, -122.418485), "i", "sub2", "id2"));
            pins.Add(new BasicMapAnnotation(new CLLocationCoordinate2D(37.786775, -122.417390), "j", "sub3", "id3"));
            pins.Add(new BasicMapAnnotation(new CLLocationCoordinate2D(37.796685, -122.416283), "k", "sub4", "id4"));

            var currentLocation = new LocationService().GetCurrentLocation();
            var visibleRegion = BuildVisibleRegion(currentLocation);

            mapView = BuildMapView(true);
            mapView.SetRegion(visibleRegion, true);

            this.View.AddSubview(mapView);

            // i have a vague idea that this delegate helps to redraw pins as user moves around screen
            mapView.Delegate = new MapViewDelegate();

            // this pin sometimes has a working callout that activates an alert and sometimes doesnt
            var testAnnotationX = new BasicMapAnnotation (new CLLocationCoordinate2D(37.786999,-122.500222), 
                                                     "made in viewdidload", "outside", "id5");
            mapView.AddAnnotation(testAnnotationX);

            // this pin collection also sometimes works but most often not
            mapView.AddAnnotations(pins.ToArray());
        }

        private MKMapView BuildMapView(bool showUserLocation)
        {
            var view = new MKMapView()
            {
                ShowsUserLocation = showUserLocation, 
            };

            view.Delegate = new MapViewDelegate();

            var testAnnotationY = new BasicMapAnnotation (new CLLocationCoordinate2D(37.800000, -122.450777), 
                                                    "made in buildmapview", "inside", "id6");

            view.AddAnnotation(testAnnotationY);

            view.SizeToFit();
            view.Frame = new RectangleF(0, 0, this.View.Frame.Width, this.View.Frame.Height);
            return view;
        }


        protected class MapViewDelegate : MKMapViewDelegate {
            protected string annotationIdentifier = "BasicAnnotation";
            UIButton detailButton; // avoid GC


            public override MKAnnotationView GetViewForAnnotation (MKMapView mapView, NSObject annotation)
            {
                if (annotation is MKUserLocation) return null;  //ignore user marker

                annotationIdentifier = (annotation as BasicMapAnnotation).Id;

                // try and dequeue the annotation view
                MKAnnotationView annotationView = mapView.DequeueReusableAnnotation(annotationIdentifier);   
                // if we couldn't dequeue one, create a new one
                if (annotationView == null)
                {
                    annotationView = new MKPinAnnotationView(annotation, annotationIdentifier);
                    //annotationView.RightCalloutAccessoryView = new UIButton(UIButtonType.DetailDisclosure); //- not required as its at bottom??

                    // configure our annotation view properties 
                    annotationView.CanShowCallout = true;
                    (annotationView as MKPinAnnotationView).AnimatesDrop = true;
                    (annotationView as MKPinAnnotationView).PinColor = MKPinAnnotationColor.Green;
                    annotationView.Selected = true;


                    // you can add an accessory view; in this case, a button on the right and an image on the left
                    detailButton = UIButton.FromType(UIButtonType.DetailDisclosure);
                    detailButton.TouchUpInside += (s, e) => {
                        Console.WriteLine ("Clicked");
                        new UIAlertView("Annotation Clicked", "You clicked on " +
                                        (annotation as MKAnnotation).Coordinate.Latitude.ToString() + ", " +
                                        (annotation as MKAnnotation).Coordinate.Longitude.ToString() , null, "OK", null).Show();
                    };

                    annotationView.RightCalloutAccessoryView = detailButton;
                }
                else // if we did dequeue one for reuse, assign the annotation to it
                    annotationView.Annotation = annotation;
                /*
                // configure our annotation view properties
                annotationView.CanShowCallout = true;
                (annotationView as MKPinAnnotationView).AnimatesDrop = true;
                (annotationView as MKPinAnnotationView).PinColor = MKPinAnnotationColor.Green;
                annotationView.Selected = true;
                */



                // fix and uncomment
                //annotationView.LeftCalloutAccessoryView = new UIImageView(UIImage.FromBundle("29_icon.png"));
                return annotationView;
            }     

            // as an optimization, you should override this method to add or remove annotations as the
            // map zooms in or out.
            public override void RegionChanged (MKMapView mapView, bool animated) {}
        }


        private MKCoordinateRegion BuildVisibleRegion(CLLocationCoordinate2D currentLocation)
        {
            var span = new MKCoordinateSpan(0.2,0.2);
            var region = new MKCoordinateRegion(currentLocation,span);

            return region;
        }



        public override void DidReceiveMemoryWarning ()
        {
            // Releases the view if it doesn't have a superview.
            base.DidReceiveMemoryWarning ();

            // Release any cached data, images, etc that aren't in use.
        }


        public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
        {
            // Return true for supported orientations
            return (toInterfaceOrientation != UIInterfaceOrientation.PortraitUpsideDown);
        }
    }

    public class BasicMapAnnotation : MKAnnotation{
        public override CLLocationCoordinate2D Coordinate {get;set;}
        string title, subtitle;
        public override string Title { get{ return title; }}
        public override string Subtitle { get{ return subtitle; }}

        public string Id {get ;set;}

        public BasicMapAnnotation (CLLocationCoordinate2D coordinate, string title, string subtitle, string id) {
            this.Coordinate = coordinate;
            this.title = title;
            this.subtitle = subtitle;
            this.Id = id;
        }
    }


    public class LocationService
    {
        private CLLocationManager locationManager;

        public LocationService()
        {
            locationManager = new CLLocationManager();
        }

        public CLLocationCoordinate2D GetCurrentLocation()
        {
            //dirty for now just to get some info.
            locationManager.StartUpdatingLocation();
            while(locationManager.Location == null);
            locationManager.StopUpdatingLocation();

            //return new CLLocationCoordinate2D ( 37.786995, -122.419280);
            return locationManager.Location.Coordinate;
        }
    }
}

Error:

Stacktrace:

at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication.UIApplicationMain (int,string[],intptr,intptr) at MonoTouch.UIKit.UIApplication.Main (string[],string,string) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:38 at singleview.Application.Main (string[]) [0x00000] in .../singleview/Main.cs:17 at (wrapper runtime-invoke) .runtime_invoke_void_object (object,intptr,intptr,intptr)

Native stacktrace:

0   singleview                          0x00091eac mono_handle_native_sigsegv + 284
1   singleview                          0x00005788 mono_sigsegv_signal_handler + 248
2   libsystem_c.dylib                   0x938658cb _sigtramp + 43
3   ???                                 0xffffffff 0x0 + 4294967295
4   UIKit                               0x0274f258 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 61
5   UIKit                               0x02810021 -[UIControl sendAction:to:forEvent:] + 66
6   UIKit                               0x0281057f -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 578
7   UIKit                               0x0280f6e8 -[UIControl touchesEnded:withEvent:] + 546
8   UIKit                               0x0277ecef -[UIWindow _sendTouchesForEvent:] + 846
9   UIKit                               0x0277ef02 -[UIWindow sendEvent:] + 273
10  UIKit                               0x0275cd4a -[UIApplication sendEvent:] + 436
11  UIKit                               0x0274e698 _UIApplicationHandleEvent + 9874
12  GraphicsServices                    0x04d40df9 _PurpleEventCallback + 339
13  GraphicsServices                    0x04d40ad0 PurpleEventCallback + 46
14  CoreFoundation                      0x012bfbf5 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 53
15  CoreFoundation                      0x012bf962 __CFRunLoopDoSource1 + 146
16  CoreFoundation                      0x012f0bb6 __CFRunLoopRun + 2118
17  CoreFoundation                      0x012eff44 CFRunLoopRunSpecific + 276
18  CoreFoundation                      0x012efe1b CFRunLoopRunInMode + 123
19  GraphicsServices                    0x04d3f7e3 GSEventRunModal + 88
20  GraphicsServices                    0x04d3f668 GSEventRun + 104
21  UIKit                               0x0274bffc UIApplicationMain + 1211
22  ???                                 0x0f4d71ad 0x0 + 256733613
23  ???                                 0x0f4d4e40 0x0 + 256724544
24  ???                                 0x0f4d4a48 0x0 + 256723528
25  ???                                 0x0f4d4b9e 0x0 + 256723870
26  singleview                          0x00009b52 mono_jit_runtime_invoke + 722
27  singleview                          0x0016d02e mono_runtime_invoke + 126
28  singleview                          0x00171224 mono_runtime_exec_main + 420
29  singleview                          0x00176615 mono_runtime_run_main + 725
30  singleview                          0x000671e5 mono_jit_exec + 149
31  singleview                          0x00204fd4 main + 1988
32  singleview                          0x00002b75 start + 53

=================================================================
Got a SIGSEGV while executing native code. This usually indicates
 a fatal error in the mono runtime or one of the native libraries 
 used by your application.
=================================================================
Was it helpful?

Solution

Looks like the good old GC Error.

Take a look at the Monotouch-Samples App exactly this Class and Line:

https://github.com/xamarin/monotouch-samples/blob/master/MapCallouts/MainViewController.cs#L108

You need to store all the Pinviews within some Collection, so the Garbage Collection doesn't try to collect them.

OTHER TIPS

What about the 'var testAnnotationX'? You might need to move that as well.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top