Problem description
When items inside a ListView are updated too quickly, the app crashes with the following error:
[INFO] : 2013-04-26 10:35:44.204 TestApp[15385:c07] *** Assertion failure in -[_UITableViewUpdateSupport _setupAnimationsForNewlyInsertedCells], /SourceCache/UIKit_Sim/UIKit-2380.17/UITableViewSupport.m:1145
Steps to reproduce
With the following code, you can reproduce the problem. When clicking on a row, the image changes quicly several times. At some point, the app hangs (no errors shown, but cannot use it anymore) and the assertion failure is shown in console.
var win = Ti.UI.createWindow({backgroundColor: 'white'});
var myTemplate = {
properties: {
height: '200dp'
},
childTemplates: [
{
type: 'Ti.UI.ImageView',
bindId: 'pic',
properties: {
width: '200dp', height: '200dp'
}
}
]
};
var listView = Ti.UI.createListView({
templates: { 'template': myTemplate },
defaultItemTemplate: 'template'
});
var section = Ti.UI.createListSection();
var data = [];
for (var i=0; i<500; i++) {
data.push({pic: {image: 'http://upload.wikimedia.org/wikipedia/commons/1/13/Facebook_like_thumb.png'}});
}
listView.addEventListener('itemclick', function(e) {
var source = e.bindId;
var index = e.itemIndex;
var data = section.getItemAt(index);
var ii = 0;
var animateLike = function () {
Ti.API.info("ii: " + ii);
data.pic.image = (ii % 2) ? 'http://upload.wikimedia.org/wikipedia/commons/1/13/Facebook_like_thumb.png' : 'http://upload.wikimedia.org/wikipedia/commons/b/b1/Not_facebook_not_like_thumbs_down.png';
section.replaceItemsAt(index, 1, [data]);
ii++;
if (ii >= 100) {
clearInterval(animator);
animator = null;
}
};
var animator = setInterval(animateLike, 1);
})
section.setItems(data);
listView.setSections([section]);
win.add(listView);
win.open();
Well two things. If you are not changing the template of the item, please use updateItemAt API of the section. Secondly what exactly are you trying to do? From the current example the thing can simply be accomplished by using the images, repeatCount and duration property of the imageView. Also trying to update every 1 ms is a little extreme. Can we please use a more sensible value. I used a 100ms and it worked fine on the simulator. Might want a larger value for devices.
Not exactly sure what the customer is trying to accomplish. Have provided workarounds for the sample attached.
First of all - thanks! What I am trying to do is to start a (40-frame) animation upon click. The image view is part of the template. I couldn't figured away how to make the animation start, so I want the old fashioned way and want to animate by changing the image in short interval to simulate animation. I used 400 ms update rate and it crashed the ListView. Will try to use updateItemAt API and report.
UPDATE: Using the updateItemAt instead of the replaceItemsAt seems to make things a lot better and updating is possible even at intervals of 100 without crash on device. Thanks again!
Another update unfortunately: I have two ListViews (one on top of the other) and the top one crashes with the same error. To mitigate I used a timer to postpone the setItems API call, but it still crashes from time to time.
Re-opening, as the same exception is raised using setItems
Please attach test code showing crash with setItems.
I have also seen cases of ListView instability when updates and scrolling are done rapidly. The code below is of course a bit extreme, but I have seen crashes and freezes of the ListView when being rapidly updated under normal scenarios - to the point where for now I have abandoned them and gone back to ScrollViews, unfortunately. To run this code just use it in place of "list_performance_remote_images.js" in the latest Kitchen Sink. This crashes/freezes reliably in iPhone 6.1 simulator.
Why is the status "resolved"? These are serious bugs, ListView appears very fragile to timing issues.
I am also suprised that this issue is marked as 'resolved'. This is a serious problem.
I've also been running into this instability. What additional info would be helpful beyond the example posted by Mark?
Reopening based on user comments.
I have just re-built my app using SDK 3.2.0.GA and I am seeing this assertion failure by just using setItems. Not sure if the insertSectionAt call plays a part. It worked fine in SDK 3.1.3.GA An example of the code that creates the issue is. Note $.list refers to a Alloy XML ListView and _collection is a Alloy collection. myListItem is a template defined in alloy. This is using alloy 1.3.0 on OSX 10.8 iOS 7.0.3
Just confirmed that is the insertSectionAt call. If I add {animate: false} to the animate properties then the problem is fixed. Would suggest this is changed back to high priority. Mainly as the default is animate = true and so will effect quite a lot of apps
Set timeout to 1000ms while fetching. It is not gonna solve the problem but it will reduce the assertion error count
Fixed by PR https://github.com/appcelerator/titanium_mobile/pull/5494 We could not reproduce the original issue in the test case, as the timeout was too low. We could reproduce the crash with a timeout of 30ms and repeated clicking the same item. i.e
var animator = setInterval(animateLike, 30);
Test code3_2_X Backport PR : https://github.com/appcelerator/titanium_mobile/pull/5496
Tested and verified the fix with: Appcelerator Studio, build: 3.2.3.201403190645 Titanium SDK, build: 3.2.3.v20140319174101 Xcode 5.1 Node.JS Version: v0.10.13 NPM Version: 1.3.2 ├── acs@1.0.14 ├── alloy@1.3.1 ├── npm@1.3.2 ├── titanium@3.2.1 └── titanium-code-processor@1.1.0 Device: iPhone5S iOS 7.1 Scrolling the list view up and down, no crash