【发布时间】:2011-07-28 07:19:31
【问题描述】:
似乎有一些东西引用了我的自定义按钮MyButton(继承自UIButton),导致它不会被垃圾收集,除非我从超级视图中删除它。这反过来又会导致它所在的视图控制器也没有被最终确定和收集。
在我的示例中,我有我的自定义按钮,但我在视图控制器上也有一个标准的UIButton,不需要从超级视图中删除即可被收集。有什么不同?长得跟我很像。
查看此代码。例如,删除了不相关的行。关于样本的一些注意事项:
-MyButton 很空。只是一个构造函数,没有其他任何东西被覆盖。
-想象MyViewController 在UINavigationController
-LoadView() 只是创建按钮,为每个按钮绑定一个事件并将其添加到视图中
-触摸_button 会将另一个MyViewController 推送到导航控制器
-在ViewDidAppear() 中从导航控制器弹出视图控制器时,我正在做一些参考清理
-在CleanUpRefs() 中,您会看到我必须从superview 中删除_myButton,以便对所有对象进行垃圾回收。 _button,另一方面不需要删除。
-我希望在从导航控制器弹出但注释掉 _myButton.RemoveFromSuperview() 时会收集整个 MyViewController,包括所有子视图。
public class MyViewController : UIViewController
{
private UIButton _button;
private MyButton _myButton;
private MyViewController _nextController;
public override void LoadView()
{
base.LoadView();
_button = UIButton.FromType(UIButtonType.RoundedRect);
_button.TouchUpInside += PushNewController;
View.AddSubview(_button);
_myButton = new MyButton();
_myButton.TouchUpInside += MyButtonTouched;
View.AddSubview(_myButton);
}
private void PushNewController(object sender, EventArgs e)
{
_nextController = new MyViewController();
NavigationController.PushViewController(_nextController, true);
}
private void MyButtonTouched(object sender, EventArgs e)
{
Console.WriteLine("MyButton touched");
}
public void CleanUpRefs()
{
//_button.RemoveFromSuperview();
_myButton.RemoveFromSuperview();
// remove reference from hooking up event handler
_button.TouchUpInside -= PushNewController;
_myButton.TouchUpInside -= MyButtonTouched;
_button = null;
_myButton = null;
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
if(_nextController != null)
{
_nextController.CleanUpRefs();
_nextController = null;
}
}
}
似乎与 MyButton 不是直接的 UIButton 的事实有所不同,因为它是继承的。但是话又说回来,为什么会有一个额外的引用计数被调用 RemoveFromSuperview() 删除,尤其是当有一个像它一样的 UIButton 不需要删除时?
(我为非常糟糕的布局道歉,stackoverflow 似乎在代码 sn-ps 上方布置项目符号时遇到问题)
更新:我向 MonoTouch 团队提交了一份错误报告。如果你想运行它,你可以从那里下载示例项目。 Bug 92.
【问题讨论】:
标签: xamarin.ios