Problem
I found ListViews to be very fragile, and crashing the app frequently. Here is an example: In Kitchen sink replace "list_performance_remote_images.js" with the code below.
Base UI --> Views --> ListView --> Remote Images In List View
Steps to reproduce
(1) After clicking "Show Me" click the back button in the iOS simulator.
(2) I put a 2 second delay between the button click and the start of appending items to the ListView.
(3) Try to click the back button at the instant *BEFORE* you actually see items appearing - i.e. as the CPU is processing the items.
(4) In about 1 in 3 cases the app will crash.
While this test may appear contrived, in real apps it happens frequently that users switch views while rendering is occurring. I am emphasizing that I have never seen such issues with ScrollViews. The ListViews need to be much more robust.
Snippet code
var listView;
function genData (){
var baseUrl = 'http://placehold.it/';
var imageUrl;
for (i=30;i<=60;i++){
for (j=30;j<=60;j++){
imageUrl = baseUrl+i+'x'+j;
listView.sections[0].appendItems([{avatar:{image:imageUrl},info:{text:'Loading Url\n'+imageUrl}}]);
}
}
}
function setupTest(win){
var myTemplate = {
properties: {height:60},
childTemplates: [
{
type: 'Ti.UI.ImageView',
bindId: 'avatar',
properties: {
left: 10,
width: 50, height: 50
},
},
{
type: 'Ti.UI.Label',
bindId: 'info',
properties: {
color: 'white',
font: { fontFamily:'Arial', fontSize: 13, fontWeight:'bold' },
left: 70, top: 5, bottom:5, wordWrap:true, ellipsize:true,
width: Ti.UI.FILL, height: 50
},
}
]
};
var section = Ti.UI.createListSection({headerTitle:'A bunch of remote images'});
listView = Ti.UI.createListView({
sections: [section],
templates: { 'template': myTemplate },
defaultItemTemplate: 'template',
backgroundColor: 'black',
});
win.add(listView);
function populateListView(){
Ti.API.info('start');
genData();
}
setTimeout(populateListView, 2000);
}
function list_performance_remote(_args) {
var win = Ti.UI.createWindow({
title:'Remote Image Test',
orientationModes:[Ti.UI.PORTRAIT],
layout:'vertical'
});
var desc = Ti.UI.createLabel({
text:'This is a list View that uses a custom template that holds an imageView and a label.\n'+
'The imageView loads remote images. Thank you placehold.it\n'+
'Expected performance is a smooth scroll experience.\n'+
'On scrolling back and forth in the list view, the right image must be loaded.(since we are reusing views)\n\n'
})
var button = Ti.UI.createButton({title:'Show Me',top:10});
win.add(desc);
win.add(button);
button.addEventListener('click',function(){
win.remove(desc);
win.remove(button);
setupTest(win);
})
return win;
}
module.exports = list_performance_remote;
Console output
Usually in the console I see just:
- [ERROR] : An error occurred running the iOS Simulator
On occasion I also see this while running this experiment:
[ERROR] : The application has crashed with an uncaught exception 'NSInvalidArgumentException'.
[ERROR] : Reason:
[ERROR] : -[__NSDictionaryM bounds]: unrecognized selector sent to instance 0xb5e5eb0
[ERROR] : Stack trace:
[ERROR] : 0 CoreFoundation 0x038fe012 __exceptionPreprocess + 178
[ERROR] : 1 libobjc.A.dylib 0x03593e7e objc_exception_throw + 44
[ERROR] : 2 CoreFoundation 0x039894bd -[NSObject(NSObject) doesNotRecognizeSelector:] + 253
[ERROR] : 3 CoreFoundation 0x038edbbc ___forwarding___ + 588
[ERROR] : 4 CoreFoundation 0x0392a77e __forwarding_prep_1___ + 14
[ERROR] : 5 KitchenSink 0x0007d54e -[TiViewProxy relayout] + 334
[ERROR] : 6 KitchenSink 0x0007c6c3 -[TiViewProxy refreshView:] + 675
[ERROR] : 7 KitchenSink 0x0007df33 -[TiViewProxy layoutChildrenIfNeeded] + 259
[ERROR] : 8 KitchenSink 0x001fb5a7 +[TiLayoutQueue layoutProxy:] + 87
[ERROR] : 9 KitchenSink 0x001fb372 performLayoutRefresh + 530
[ERROR] : 10 CoreFoundation 0x038bd376 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22
[ERROR] : 11 CoreFoundation 0x038bce06 __CFRunLoopDoTimer + 534
[ERROR] : 12 CoreFoundation 0x038a4a82 __CFRunLoopRun + 1810
[ERROR] : 13 CoreFoundation 0x038a3f44 CFRunLoopRunSpecific + 276
[ERROR] : 14 CoreFoundation 0x038a3e1b CFRunLoopRunInMode + 123
[ERROR] : 15 GraphicsServices 0x0382d7e3 GSEventRunModal + 88
[ERROR] : 16 GraphicsServices 0x0382d668 GSEventRun + 104
[ERROR] : 17 UIKit 0x0138fffc UIApplicationMain + 1211
[ERROR] : 18 KitchenSink 0x00004ad8 main + 456
[ERROR] : 19 KitchenSink 0x000033e5 start + 53
[ERROR] : 20 ??? 0x00000001 0x0 + 1
[ERROR] : 2013-07-12 10:58:13.643 KitchenSink[38581:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryM bounds]: unrecognized selector sent to instance 0xb5e5eb0'
[ERROR] : *** First throw call stack:
[ERROR] : (0x38fe012 0x3593e7e 0x39894bd 0x38edbbc 0x392a77e 0x7d54e 0x7c6c3 0x7df33 0x1fb5a7 0x1fb372 0x38bd376 0x38bce06 0x38a4a82 0x38a3f44 0x38a3e1b 0x382d7e3 0x382d668 0x138fffc 0x4ad8 0x33e5 0x1)
-- End simulator log ---------------------------------------------------------
[ERROR] : An error occurred running the iOS Simulator
Titanium Command-Line Interface, CLI version 3.3.0, Titanium SDK version 3.3.0.GA iOS 7
Closing ticket as the issue cannot be reproduced and due to the above comments.