2011-04-06 87 views
1

我正在呈现一个UIViewController的模态,该视图包含各种UITextFields。我已覆盖模式视图InputAccessoryView,以便它显示一个简单的视图,其中一个按钮将从每个UITextField开始ResignFirstResponder,从而解除键盘锁定。Modal View析构函数在InputAccessoryView被覆盖时未被调用

最近我一直在打击内存相关的问题,所以我所有的控制器现在都有一个析构函数。我注意到,每当键盘显示与此覆盖InputAccessoryView每当模态视图被解散,析构函数将不会被调用。这是否意味着UIViewController没有被销毁?我错误地显示InputAccessoryView?

InputAccessoryView代码如下:

bool accessoryViewInit = false; 
UIView accessoryView = new UIView(new RectangleF(0,0,320,30)); 

public override UIView InputAccessoryView 
{ 
    get 
    { 
     if (!accessoryViewInit) 
     { 
      accessoryView.BackgroundColor = UIColor.FromRGBA(0.0f, 0.0f, 0.f, 0.5f); 
      UIButton dismiss = new UIButton(new RectangleF(50,1, 200, 28)); 
      dismiss.BackgroundColor = UIColor.Blue; 
      dismiss.SetTitle("Close Keyboard", UIControlState.Normal); 
      dismiss.TouchUpInside += delegate(object sender, EventArgs e) { 
       field1.ResignFirstResponder(); 
       field2.ResignFirstResponder(); 
       field3.ResignFirstResponder(); 
      }; 
      accessoryView.AddSubview(dismiss); 
     }  
     return accessoryView; 
    } 
} 

我有一种感觉,是因为我指定一个委托给TouchUpInside事件的按钮,它是保持引用到这样一个事实,从而阻止整个控制器被破坏?

我已经创建可在https://github.com/lukewhitt/InputAccessoryView-test

找到重现问题的示例项目:运行应用程序,通过触摸大红色按钮当前模式的看法。现在,如果您在不显示键盘的情况下解除视图,将会调用析构函数。如果你在UITextField的第一响应者(显示键盘和InputAccessoryView)上打开模式控制器,则不会调用析构函数。

编辑

这样看来,这是一个MonoTouch的错误,将被固定在了崭露头角的释放。为了解决这个问题,在分配事件时,你似乎不能使用匿名代理。所以dismiss.TouchUpInside将成为:

public override UIView InputAccessoryView { 
// code before 
    dismiss.TouchUpInside += HandleDismissTouch; 
// rest of code 
} 

private void HandleDismissTouch (object sender, EventArgs e) 
{ 
    field1.ResignFirstResponder(); 
    field2.ResignFirstResponder(); 
    field3.ResignFirstResponder(); 
} 

然后在驳回模态控制器的代码,我已经添加了以下内容:

if (dismiss != null) 
{ 
    dismiss.TouchUpInside -= HandleDismissTouch; 
    dismiss.Dispose(); 
    dismiss = null; 
} 

这将导致析构函数被调用!

回答

1

我觉得你面对MT中的错误将被固定在MT 4貌似事件处理程序可能会阻止释放控制器:

UIView events and garbage collection

不幸的是,杰夫一直没有回复后续后续海报质疑这种影响,以及如果在MT4之前使用匿名代表进行事件是一个问题。

我认为现在有效的解决方案是手动Dispose()。

+0

感谢您指点我正确的方向! – Luke 2011-04-06 13:32:40

+0

我会检查我的代码是否有类似的问题。仍然会很有趣,知道a)当MT4将被发布时,以及b)什么是最好的方式来防止旧MT发布中的问题。 – Krumelur 2011-04-06 13:38:50