Created
May 1, 2012 11:05
-
-
Save sgmunn/2567352 to your computer and use it in GitHub Desktop.
Event Handler in MonoTouch not allowing objects to be collected
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Drawing; | |
using MonoTouch.Foundation; | |
using MonoTouch.UIKit; | |
namespace UIDateFieldTest | |
{ | |
public partial class UIDateFieldTestViewController : UIViewController | |
{ | |
public UIDateFieldTestViewController() : base ("UIDateFieldTestViewController", null) | |
{ | |
} | |
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(); | |
// Perform any additional setup after loading the view, typically from a nib. | |
} | |
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; | |
ReleaseDesignerOutlets(); | |
} | |
public override bool ShouldAutorotateToInterfaceOrientation(UIInterfaceOrientation toInterfaceOrientation) | |
{ | |
// Return true for supported orientations | |
return (toInterfaceOrientation != UIInterfaceOrientation.PortraitUpsideDown); | |
} | |
partial void buttonClicked(MonoTouch.Foundation.NSObject sender) | |
{ | |
var tbView = new UITableViewController(); | |
tbView.TableView.DataSource = new TestSource(); | |
this.NavigationController.PushViewController(tbView, true); | |
} | |
} | |
public class TestSource : UITableViewDataSource | |
{ | |
public override int NumberOfSections(UITableView tableView) | |
{ | |
return 1; | |
} | |
public override int RowsInSection(UITableView tableView, int section) | |
{ | |
return 2; | |
} | |
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath) | |
{ | |
if (indexPath.Row == 0) | |
{ | |
var cell1 = tableView.DequeueReusableCell(new NSString("Cell1")); | |
if (cell1 == null) | |
{ | |
cell1 = new TextInputTableViewCell(UITableViewCellStyle.Default, new NSString("Cell1")); | |
} | |
return cell1; | |
} | |
var cell2 = tableView.DequeueReusableCell(new NSString("Cell2")); | |
if (cell2 == null) | |
{ | |
cell2 = new DateInputTableViewCell(UITableViewCellStyle.Default, new NSString("Cell2")); | |
} | |
return cell2; | |
} | |
} | |
public class TextInputTableViewCell : UITableViewCell | |
{ | |
private UITextField textField; | |
public TextInputTableViewCell(UITableViewCellStyle style, NSString reuseIdentifer) | |
: base(style, reuseIdentifer) | |
{ | |
this.ConfigureCell(); | |
} | |
public UITextField TextField | |
{ | |
get | |
{ | |
return this.textField; | |
} | |
} | |
protected override void Dispose (bool disposing) | |
{ | |
Console.WriteLine("dispose textField {0}", disposing); | |
if (disposing) | |
{ | |
this.textField.Dispose(); | |
this.textField = null; | |
} | |
base.Dispose (disposing); | |
} | |
protected void ConfigureCell () | |
{ | |
this.SelectionStyle = UITableViewCellSelectionStyle.None; | |
this.textField = new UITextField(this.CalculateTextFieldFrame(string.Empty)) | |
{ | |
VerticalAlignment = UIControlContentVerticalAlignment.Center, | |
ClearButtonMode = UITextFieldViewMode.WhileEditing, | |
}; | |
this.textField.Font = UIFont.SystemFontOfSize(17); | |
this.textField.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleLeftMargin; | |
this.ContentView.AddSubview(this.textField); | |
this.textField.Ended += this.TextValueChanged; | |
} | |
private void TextValueChanged(object sender, EventArgs args) | |
{ | |
} | |
private RectangleF CalculateTextFieldFrame(string textValue) | |
{ | |
float margin = 10; | |
var textSize = new RectangleF (margin, 10, this.ContentView.Bounds.Width - (margin * 2), this.ContentView.Bounds.Height - (margin * 2)); | |
if (!String.IsNullOrEmpty(textValue)) | |
{ | |
var sz = this.CalculateEntrySize(null); | |
textSize = new RectangleF (sz.Width, (this.ContentView.Bounds.Height - sz.Height) / 2 - 1, sz.Width * 2 - margin, sz.Height); | |
} | |
return textSize; | |
} | |
private SizeF CalculateEntrySize (UITableView tv) | |
{ | |
var sz = this.StringSize("W", UIFont.SystemFontOfSize (17)); | |
float w = this.ContentView.Bounds.Width / 3; | |
return new SizeF(w, sz.Height); | |
} | |
} | |
public class DateInputTableViewCell : UITableViewCell | |
{ | |
private UIDateField dateField; | |
public DateInputTableViewCell(UITableViewCellStyle style, NSString reuseIdentifer) | |
: base(style, reuseIdentifer) | |
{ | |
this.ConfigureCell(); | |
} | |
protected override void Dispose (bool disposing) | |
{ | |
Console.WriteLine("dispose ..{0}", disposing); | |
if (disposing) | |
{ | |
this.dateField.Dispose(); | |
this.dateField = null; | |
} | |
base.Dispose (disposing); | |
} | |
protected void ConfigureCell () | |
{ | |
this.SelectionStyle = UITableViewCellSelectionStyle.None; | |
this.dateField = new UIDateField(this.CalculateTextFieldFrame(string.Empty)) | |
{ | |
AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleLeftMargin, | |
}; | |
this.ContentView.AddSubview(this.dateField); | |
// FIXME: More investigation required here, hooking this handler up causes the datefield and the table cell to be not collected | |
this.dateField.ValueChanged += this.DateValueChanged; | |
} | |
private void DateValueChanged(object sender, EventArgs args) | |
{ | |
} | |
private RectangleF CalculateTextFieldFrame(string textValue) | |
{ | |
float margin = 10; | |
var textSize = new RectangleF (margin, 10, this.ContentView.Bounds.Width - (margin * 2), this.ContentView.Bounds.Height - (margin * 2)); | |
if (!String.IsNullOrEmpty(textValue)) | |
{ | |
var sz = this.CalculateEntrySize(null); | |
textSize = new RectangleF (sz.Width, (this.ContentView.Bounds.Height - sz.Height) / 2 - 1, sz.Width * 2 - margin, sz.Height); | |
} | |
return textSize; | |
} | |
private SizeF CalculateEntrySize (UITableView tv) | |
{ | |
var sz = this.StringSize("W", UIFont.SystemFontOfSize (17)); | |
float w = this.ContentView.Bounds.Width / 3; | |
return new SizeF(w, sz.Height); | |
} | |
} | |
public class UIDateField : UIControl | |
{ | |
private DateTime date; | |
private UIDatePicker picker; | |
private UILabel label; | |
private string dateFormat; | |
private UIView accessoryView; | |
public UIDateField(RectangleF frame) : base(frame) | |
{ | |
this.dateFormat = "D"; | |
this.picker = new UIDatePicker(); | |
this.picker.Mode = UIDatePickerMode.Date; | |
this.picker.TimeZone = NSTimeZone.FromAbbreviation("GMT"); | |
this.picker.ValueChanged += this.PickerValueChanged; | |
this.label = new UILabel(this.Bounds); | |
this.label.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleLeftMargin; | |
this.label.BackgroundColor = UIColor.Green; | |
this.label.UserInteractionEnabled = false; | |
this.AddSubview(this.label); | |
this.Date = DateTime.Today; | |
} | |
~UIDateField() | |
{ | |
Console.WriteLine("UIDateField"); | |
} | |
public override bool CanBecomeFirstResponder | |
{ | |
get | |
{ | |
return this.Enabled; | |
} | |
} | |
public override UIView InputView | |
{ | |
get | |
{ | |
return this.picker; | |
} | |
} | |
[Export("inputAccessoryView")] | |
public new UIView InputAccessoryView | |
{ | |
get | |
{ | |
return this.accessoryView; | |
} | |
set | |
{ | |
this.accessoryView = value; | |
} | |
} | |
public DateTime Date | |
{ | |
get | |
{ | |
return this.date; | |
} | |
set | |
{ | |
if (value != this.date) | |
{ | |
this.date = value; | |
this.picker.Date = DateTime.SpecifyKind(value, DateTimeKind.Utc); | |
this.label.Text = this.date.ToString(this.DateFormat); | |
} | |
} | |
} | |
public string DateFormat | |
{ | |
get | |
{ | |
return this.dateFormat; | |
} | |
set | |
{ | |
this.dateFormat = value; | |
this.label.Text = this.date.ToString(this.DateFormat); | |
} | |
} | |
public override void TouchesEnded(MonoTouch.Foundation.NSSet touches, UIEvent evt) | |
{ | |
base.TouchesEnded(touches, evt); | |
if (evt.Type == UIEventType.Touches) | |
{ | |
if (this.IsFirstResponder) | |
{ | |
this.ResignFirstResponder(); | |
} | |
else | |
{ | |
this.BecomeFirstResponder(); | |
} | |
} | |
} | |
protected override void Dispose(bool disposing) | |
{ | |
Console.WriteLine("dispose UIDateField"); | |
if (disposing) | |
{ | |
this.picker.Dispose(); | |
this.picker = null; | |
this.label.Dispose(); | |
this.label = null; | |
} | |
base.Dispose(disposing); | |
} | |
private void PickerValueChanged(object sender, EventArgs args) | |
{ | |
this.Date = DateTime.SpecifyKind(this.picker.Date, DateTimeKind.Unspecified); | |
this.SendActionForControlEvents(UIControlEvent.ValueChanged); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment