【问题标题】:Clicking a SegmentedControl to UITableViewCell in Monotouch causes SIGABRT在 Monotouch 中单击 SegmentedControl 到 UITableViewCell 会导致 SIGABRT
【发布时间】:2013-01-07 18:19:26
【问题描述】:

在我用于 iPhone 的 Monotouch 应用程序中,我尝试将分段控制器添加到 UITableViewCell 以作为每行中值的切换。一切都正确显示,单击时第一行最初将正常工作。但是,在该行离开屏幕并重新加载后,如果我再次单击分段控制器,我会收到异常:

由于未处理的异常而终止运行时 [错误] 致命的未处理异常:System.Exception:在已被 GC 处理的 MonoTouch.UIKit.UIControlEventProxy (0x16D793C0) 类型的托管对象上从 Objective-c 调用选择器 ---> System.MissingMethodException:未找到 MonoTouch 的构造函数.UIKit.UIControlEventProxy::.ctor(System.IntPtr)

我听说过使用 Monotouch 的人尝试将按钮放在表格单元格中的类似问题。一般建议是将每个表格单元格添加到列表中以防止其被垃圾收集,但这对我不起作用。

有解决这个问题的办法吗?

这是我的 GetCell 代码的简化版本:

public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
        {

            Hashtable rowData = dataList [indexPath.Row];
            FilterListToggleCell cell;
            cell = (FilterListToggleCell)tableView.DequeueReusableCell ("FilterTogglePlusCell");


            cacheList.Add(cell.Toggle);//cache only the segcontrol
                            //cacheList.Add(cell);//also previously tried caching the whole cell


            cell.Title.Text = (string)rowData["title"];
            if(additionalFields.Contains((string)rowData["key"])){
                cell.Toggle.SelectedSegment = 0;
            } else {
                cell.Toggle.SelectedSegment = 1;

            }



            cell.Toggle.ValueChanged += (sender, e) => {
                UISegmentedControl toggle = (UISegmentedControl)sender;

                if(toggle.SelectedSegment == 0){
                    Console.WriteLine("Toggle YES");
                } else {
                    Console.WriteLine("Toggle NO");
                }

            };



            cell.Toggle.Tag = indexPath.Row;

            return cell;

        }

【问题讨论】:

    标签: uitableview xamarin.ios sigabrt


    【解决方案1】:

    基本条件你是对的。发生这种情况是因为没有对您从GetCell 方法返回的UITableViewCell托管 引用。因此,GC 可以收集并释放它(这将导致诸如想要回调托管实例的事件之类的问题)。有关详细信息,请参阅此answer

    现在我不确定为什么这种方法不适合您。但是您上面的代码似乎不完整,例如

    cell = (FilterListToggleCell)tableView.DequeueReusableCell ("FilterTogglePlusCell");
    

    可以返回null,此时您应该创建更多单元格(事实上,没有条件可以实际创建任何新单元格,因此没有任何东西可以重复使用)。

    cell 为空时(因为cell.Toggle),您的下一行将抛出NullReferenceException

    请注意,这并不能解释您的崩溃 - 我怀疑缺少一些使其工作的代码(创建单元格)并且可能无法正确缓存它们。

    【讨论】:

    • 上述代码中的问题(即使缓存托管单元格)可能是由“cell.Toggle.ValueChanged += (sender, e)”引起的。如果单元格已被使用,则第二次将有两个事件处理程序,第三次将有三个事件处理程序,依此类推。然而,先前的处理程序将引用一个可能现在不再有效的单元格/UISegmentedControl 并崩溃。我建议使事件处理程序不是匿名的,而是一个真正的方法,并在通过调用“cell.Toggle.ValueChanged -= MyHandler; cell.Toggle.ValueChanged += MyHandler;”重新分配它之前将其删除。
    • 好点 wrt 多个事件处理程序。通常,事件仅在创建单元时设置,而不是在重新使用单元时设置。
    【解决方案2】:

    根据来自以下问题的信息,我能够在不需要额外缓存的情况下完成这项工作:How do I remove/unregister event handler from an event?

    ValueChanged 行被替换为:

    cell.Toggle.AddTarget(this, new Selector("ToggleChange"),UIControlEvent.ValueChanged);
    

    另一个方法被添加到我的 UITableViewDataSource

    [Export ("ToggleChange")]
    void OnChange(UISementedControl toggle){
        if(toggle.SelectedSegment == 0){
            Console.WriteLine("Toggle YES");
        } else {
            Console.WriteLine("Toggle NO");
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-04
      • 1970-01-01
      • 1970-01-01
      • 2015-09-30
      • 1970-01-01
      相关资源
      最近更新 更多