请帮助我,我做错了什么。
我使用示例中的BubbleCell
和BubbleElement
。
由于未知原因,应用程序有时会在本机代码中崩溃。
如果我不使用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。对不起我的英文...它由谷歌翻译。
答案 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。