Monotouch使用UITableView在本机代码中随机崩溃

时间:2012-07-17 15:32:45

标签: ios uitableview garbage-collection xamarin.ios monotouch.dialog

请帮助我,我做错了什么。

我使用示例中的BubbleCellBubbleElement。 由于未知原因,应用程序有时会在本机代码中崩溃。 如果我不使用DequeueReusableCell,我会尝试稍微纠正一下情况,并始终创建一个新的BubbleCell。 此外,如果构造函数BubbleElement将字符串常量作为标题而不是对象字段传递,则问题将消失。

Stacktrace:http://pastebin.com/KAYzpHDk


问题比看上去更深刻。 你的建议没有帮助,应用程序仍然崩溃。

我做了一个单独的项目,只留下显示问题所需的最少代码。 问题以某种方式与System.Json有关......也许。

以下是该项目的存档: https://dl.dropbox.com/u/63074515/BubbleNativeCrash.zip

行动顺序: 1)打开项目 2)编译并运行模拟器而不进行调试(配置Debug | iPhoneSimulator) 3)在第一个视图中单击horse1 4)在显示的列表中,向上和向下滚动整个项目几次 5)在我的情况下,在这个阶段我们崩溃...(堆栈跟踪:http://pastebin.com/KAYzpHDk

如果没有立即失败,您可以返回联系人列表,反之亦然,甚至几次。 失败的速度取决于聊天中的消息数量。

现在有趣的部分。 如果在ChatViewController.cs中注释406行并取消注释第407行,问题就会完全消失(或者我无法在合理的时间内重复):

// string messageText = msg.MessageText ?? string.Empty;
string messageText = "Hello, World!!!";

也就是说,将一个常量字符串传递给BubbleElement构造函数。 在那之后,我想这个问题不再重复了。

我试图按原样保留所有内容,但删除了Json的工作 - 问题消失了。 仅当BubbleElement从JsonValue(第36行的IM \ IMMessage.cs)读取字符串时才出现此问题。 即使在IMMessage.cs中为MessageText设置一个常量字符串 - 问题也会消失。

我做错了什么? :)

P.S。对不起我的英文...它由谷歌翻译。

1 个答案:

答案 0 :(得分:1)

您不保留对从GetCell返回的托管实例的任何引用。因此,一旦方法返回,GC可以(并且将会)收集托管实例,而原生实例将继续存在(因为它在iOS中被引用)。

使用UITableViewCell时,此方法正常,因为所有状态都保留在原生实例中。但是,如果您从中继承并添加自己的托管字段,则情况并非如此。在这种情况下,您将无法访问托管状态,因为它不存在(您将拥有的实例将不是您创建的实例)。

解决此问题的简单方法是保留对您创建的BubbleCell的引用,例如在列表中,因此GC不会收集它们。

    static List<BubbleCell> cell_cache = new List<BubbleCell> ();

    public override UITableViewCell GetCell(UITableView tableView)
    {
        var cell = tableView.DequeueReusableCell(isLeft ? BubbleCell.KeyLeft : BubbleCell.KeyRight) as BubbleCell;
        if (cell == null) {
            cell = new BubbleCell(isLeft);
            cells_cache.Add (cell);
        }
        cell.Update(Caption);
        return cell;
    }

一旦不再需要单元格(例如关闭UITableView时),请不要忘记清除列表。

更新额外信息

cell_cache必须是static,否则无法帮助(我的错误,在上面修复)以保持参考有效。但是,正如您所发现的那样,这不是针对此案例的解决方案(来源显示可以重复使用单元格)。

OTOH问题与使用JSON无关。使用相同的string消息(例如,从数组中)会导致相同的崩溃。这有点奇怪,我会进一步投资......

最终更新

事实证明,CreateResizableImage的来电可能会触及iOS bug。解决方法是使用较旧的StretchableImage API。该问题已(重新)提交给Apple。