Monotouch mapkit mkannotation 集合给出错误

Posted

技术标签:

【中文标题】Monotouch mapkit mkannotation 集合给出错误【英文标题】:Monotouch mapkit mkannotation collection gives errors 【发布时间】:2013-04-03 22:29:10 【问题描述】:

monotouch aka xamarin ios 的新手。试图让一个强大的 mapkit 工作,可以占用许多引脚。试验一个我从各种我能找到的来源拼凑而成的基本示例。

收到零星的 SIGSEGV 错误。当单击引脚以显示有时有效有时无效的警报框时,似乎是某种内存错误。

我不确定我哪里出错了。这是正确的路线吗?这是代码

    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;
        
    

错误:

堆栈跟踪:

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

本机堆栈跟踪:

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.
=================================================================

【问题讨论】:

【参考方案1】:

看起来像旧的 GC 错误。

看看 Monotouch-Samples App 的这个类和行:

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

您需要将所有 Pinview 存储在某个 Collection 中,因此 Garbage Collection 不会尝试收集它们。

【讨论】:

嘿 Max 感谢您的帮助。在代码中,我在顶部有这个 List pins = new List();这似乎与示例相同,即方法外部的数组/列表类型变量以放置引脚注释,那么为什么这对于 GC 来说还不够:?【参考方案2】:

“var testAnnotationX”怎么样?您可能还需要移动它。

【讨论】:

以上是关于Monotouch mapkit mkannotation 集合给出错误的主要内容,如果未能解决你的问题,请参考以下文章

Monotouch - 缓存地图以供离线使用

MonoTouch:播放声音

Monotouch - 在 monotouch 项目中附加 Sqlite 数据库并部署到 iPad

Monotouch:了解委托机制模式

如何在 DialogViewController (Monotouch.Dialog) 上设置背景颜色

Monotouch 找不到 AudioFileOpenURL