Reputation: 81
Please help me, what am I doing wrong.
I use BubbleCell
and BubbleElement
from the examples.
For unknown reasons, the application sometimes crashes in native code.
I try out a little bit to correct the situation if I do not use DequeueReusableCell
, and always create a new BubbleCell
.
Also, the problem disappears if the constructor BubbleElement
to pass a string constant as the caption, not the object field.
Stacktrace: http://pastebin.com/KAYzpHDk
The problem is deeper than it seems. Your suggestion doesn't help, the application still crashes.
I made a separate project, leaving it a minimum of code necessary to show the problem. The problem is somehow related to System.Json... maybe.
Here is an archive of the project: https://dl.dropbox.com/u/63074515/BubbleNativeCrash.zip
The sequence of actions: 1) open the project 2) compile and run the emulator without debugging (configuration Debug|iPhoneSimulator) 3) click horse1 in the first view 4) in the list that appears, scroll whole items a few times up and down 5) in my case at this stage we crash... (stack trace: http://pastebin.com/KAYzpHDk)
If not immediately fail, you can return to the contact list, and vice versa, or even once a few times. How quickly will fail depends on the number of messages in the chat.
Now the fun part. The problem disappears completely (or I can not repeat it in a reasonable time) if in ChatViewController.cs comment the line 406 and uncomment line 407:
// string messageText = msg.MessageText ?? string.Empty;
string messageText = "Hello, World!!!";
That is, make a constant string passed into BubbleElement constructor. After that, the problem does not repeat, I think.
I tried to leave everything as is, but remove the work with the Json - the problem disappears. The problem in only when BubbleElement takes a string read from the JsonValue (IM\IMMessage.cs at line 36). Even if there is, in IMMessage.cs, to set a constant string for MessageText - the problem disappears.
What am I doing wrong? :)
p.s. Sorry for my english... it powered by google translate.
Upvotes: 2
Views: 382
Reputation: 43553
You do not keep any reference to the managed instance you return from GetCell
. As such the GC can (and will) collect the managed instance once the method returns while the native instance will continue to live (since it's referenced inside iOS).
This works fine when you use UITableViewCell
since all the state is kept inside the native instance. However this is not the case if you inherit from it and add your own managed fields. In such cases you won't be able to access the managed state since it won't exists (the instance you'll have won't be the one you created).
The easy way to solve this is to keep a reference to the BubbleCell
you create, e.g. in a list, so the GC won't collect them.
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;
}
Do not forget to clear the list once the cells are not needed anymore (e.g. when closing the UITableView
).
UPDATE FROM EXTRA INFORMATION
The cell_cache
must be static
or it won't help (my mistake, fixed above) to keep references alive. But, as you found out, it's not the fix for this case (source shows the cells can be reused).
OTOH the issue is not related to using JSON. Using the same string
messages (e.g. from an array) results in the same crash. That's a bit weird and I'll investgate this further...
FINAL UPDATE
It turns out the calls to CreateResizableImage
can hit an iOS bug. The workaround is to use the older StretchableImage
API. The issue was (re)submitted to Apple.
Upvotes: 1