Presenting the bar chart controller in a view controller crashes the second time - Xamarin (1)


#1

Here is the description of the issue.

 

 

  1.  We create a bar chart controller to create a custom bar chart

  2.  We present the view controller and the bar chart shows up fine

  3.  We use a close button to dismiss the view controller

  4.  We create and present the bar chart controller once again 

  5.  It crashes .( sometimes after we show the chart and sometimes as soon as the present view controller is initiated )

 

    We dont know if we have a memory leak that causes this or dismiss view controller causes the problem. 


#2
BarChartViewController.cs

using System;
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.UIKit;

using ShinobiCharts;

namespace presention
{
	public partial class BarChartViewController : UIViewController
	{
		private BarChart _chart;
		private readonly BarChartDataSource _dataSource;
		private readonly BarChartDelegate _delegate = new BarChartDelegate();

		public BarChartViewController (BarChartDataProvider dataProvider)
			: base ("BarChartViewController", null)
		{
			_dataSource = new BarChartDataSource (dataProvider);
		}

		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 void ViewDidLoad ()
		{
			base.ViewDidLoad ();


			// Create our chart
			_chart = new BarChart (CalcChartFrame(), UIUserInterfaceIdiom.Pad);

			// Give the chart the data source and a delegate
			_chart.DataSource = _dataSource;
			_chart.Delegate = _delegate;

			#warning If you have a trial version, you need to uncomment the next line and enter your licence key where the empty string is:
			_chart.LicenseKey = "" // our license key

			// Add the chart to the view controller
			View.AddSubview (_chart);

		}

		[Obsolete]
		public override void ViewDidUnload ()
		{
			base.ViewDidUnload ();

			// Clear any references to subviews of the main view in order to
			// allow the Garbage Collector to collect them sooner.
			//
			// e.g. myOutlet.Dispose (); myOutlet = null;
			_chart = null;

// ReleaseDesignerOutlets ();
		}

		[Obsolete]
		public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
		{
			// Return true for supported orientations
			return false;
		}



		private void AnimateBars (object sender, EventArgs args)
		{
			// Reload data to reset the animation
			_chart.ReloadData ();
			// Trigger a redraw so animation will start immediately 
			_chart.RedrawChart();
		}


		private RectangleF CalcChartFrame ()
		{
			RectangleF chartFrame;

			chartFrame = new RectangleF (50, 150, View.Bounds.Size.Width - 100, View.Bounds.Size.Height - 200);

			return chartFrame;
		}		

		partial void goBack(NSObject sender)
		{
			this.DismissViewController(true, null);
		}
	}

}

BarChart.cs

using System;
using System.Collections.Generic;
using System.Drawing;

using MonoTouch.Foundation;
using MonoTouch.ObjCRuntime;
using MonoTouch.UIKit;

using ShinobiCharts;

namespace presention
{
	public class BarChartDataProvider
	{

		public BarChartDataProvider ()
		{
		}

		public int NumberOfPoints { get { return 5; } }

		public int NumberOfSeries { get { return 3; } }

		public float GetDataAt(int dataIndex, int seriesIndex)
		{
			return dataIndex * 1.5f + seriesIndex * 0.1f;
		}

	}

	public class BarChartDataSource : SChartDataSource
	{

		private readonly BarChartDataProvider _dataProvider;

		public BarChartDataSource(BarChartDataProvider dataProvider)
		{
			_dataProvider = dataProvider;
		}

		// In this sample the data provider knows how much data it has
		public override int GetNumberOfDataPoints (ShinobiChart chart, int seriesIndex)
		{
			return _dataProvider.NumberOfPoints;
		}

		// The chart knows how to create its series
		public override SChartSeries GetSeries (ShinobiChart chart, int index)
		{   	
			return ((BarChart)chart).CreateSeries(index);	
		}

		// In this sample the data provider knows how much data it has
		public override int GetNumberOfSeries (ShinobiChart chart) 
		{
			return _dataProvider.NumberOfSeries;
		}

		// Returns the data point at the specified index for the given series/chart.
		public override SChartData GetDataPoint (ShinobiChart chart, int dataIndex, int seriesIndex)
		{

			//Construct a data point and return
			//The y axis is going to be a category axis, so set the y value
			//of the data point to a different string based on the data index
			//Set the x value to a random number between 0 and 10
			return new SChartDataPoint() 
			{
				YValue = new NSString ("Label " + (dataIndex+1)),
				XValue = new NSNumber (_dataProvider.GetDataAt(dataIndex, seriesIndex))
			};
		}
	}
	public class BarChartDelegate : SChartDelegate
	{

		public BarChartDelegate ()
		{
		}

		protected override void OnToggledSelection (ShinobiChart chart, SChartDataPoint dataPoint, SChartSeries series, System.Drawing.PointF pixelPoint)
		{
			System.Diagnostics.Debug.WriteLine("OnToggledSelection");
		}

	}
	public class BarChart : ShinobiChart
	{

		private const float _barBaseline = 3f;

		public BarChart(RectangleF frame, UIUserInterfaceIdiom uiIdiom)
			: base(frame)
		{
			Setup (uiIdiom);
		}

		// In this sample all series are bar series.
		public SChartBarSeries CreateSeries(int index)
		{   	

			//In our example all series are bar series.
			return new SChartBarSeries ()
			{
				Title = new NSString ("Bar #" + (index+1)),
				CrosshairEnabled = true, //Allows crosshair to track the series

				//The series will be animated from the baseline to their normal 
				//position when data is loaded/reloaded
				AnimationEnabled = true,

				// Baseline for the bar series, bars will be filled down/up to this value
				Baseline = new NSNumber (_barBaseline),

				SelectionMode = SChartSelection.Point
			};
		}

		private void Setup(UIUserInterfaceIdiom uiIdiom)
		{
			// As the chart is a UIView, set its resizing mask to allow it to automatically resize when screen orientation changes.
			AutoresizingMask = ~UIViewAutoresizing.None;

			// Create a number axis for the x axis, and disable panning and zooming
			XAxis = new SChartNumberAxis ();
			XAxis.EnableGesturePanning = false;
			XAxis.EnableGestureZooming = false;
			XAxis.RangePaddingLow = new NSNumber (0.75);
			XAxis.RangePaddingHigh = new NSNumber (0.75);

			// Create a category axis for the y axis, and disable panning and zooming
			YAxis = new SChartCategoryAxis ();
			YAxis.EnableGesturePanning = false;
			YAxis.EnableGestureZooming = false;

			// The y axis is going to be positioned at this value on the x axis
			YAxis.AxisPositionValue = new NSNumber (_barBaseline);
			// The axis tick labels are going to stay at their original position when the axis moves to its designated position
			YAxis.AxisLabelsAreFixed = true;

			//Set the chart title
			Title = "Bar Series Chart";
			TitleLabel.Font = UIFont.FromName ("TrebuchetMS", (uiIdiom == UIUserInterfaceIdiom.Pad) ? 27.0f : 17.0f);
			TitleLabel.TextColor = UIColor.Black;

			if (uiIdiom == UIUserInterfaceIdiom.Pad) {    	
				//Show the legend
				Legend.Hidden = false;
				Legend.Style.Font = UIFont.FromName (@"Futura", 17.0f);
				Legend.SymbolWidth = new NSNumber (75);
				Legend.Style.BorderColor = UIColor.Clear;
			}
		}

	}
}