{ "id": "93074", "key": "TIMOB-9491", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [], "resolution": { "id": "7", "description": "", "name": "Invalid" }, "resolutiondate": "2012-06-19T18:02:49.000+0000", "created": "2012-06-11T17:35:41.000+0000", "priority": { "name": "Medium", "id": "3" }, "labels": [ "SupportTeam", "api", "support" ], "versions": [ { "id": "13273", "description": "Release 2.0.2", "name": "Release 2.0.2", "archived": false, "released": true, "releaseDate": "2012-05-31" }, { "id": "13272", "description": "Release 2.0.1", "name": "Release 2.0.1", "archived": true, "released": true, "releaseDate": "2012-04-16" } ], "issuelinks": [], "assignee": { "name": "vduggal", "key": "vduggal", "displayName": "Vishal Duggal", "active": false, "timeZone": "America/Los_Angeles" }, "updated": "2017-05-31T22:37:09.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [ { "id": "10206", "name": "iOS", "description": "iOS Platform" } ], "description": "h2. Problem\r\n\r\nWhen adding rows to a table view dynamically each time the table has scrolled close to the end, the scrolling becomes jerky and the app is unresponsive. The table rows contain images and labels.\r\n\r\nh2. Test Case\r\n\r\n{code}\r\nvar buildRow = function() {\r\n\tvar rowView = Titanium.UI.createTableViewRow({\r\n\t\tclassName : 'lolcat',\r\n\t\tlayout : \"vertical\",\r\n\t\theight : 350,\r\n\t\tbackgroundColor : 'pink'\r\n\t});\r\n\r\n\tvar imgAvatar = Titanium.UI.createImageView({\r\n\t\timage : 'http://placekitten.com/g/50/50',\r\n\t\theight : 50,\r\n\t\twidth : 50,\r\n\t\ttop : 5,\r\n\t\tleft : 5\r\n\t});\r\n\r\n\trowView.add(imgAvatar);\r\n\r\n\tvar avaLabel = Ti.UI.createLabel({\r\n\t\ttext : \"Super Cat\",\r\n\t\tfont : {\r\n\t\t\tfontSize : 12,\r\n\t\t\tfontWeight : 'bold'\r\n\t\t},\r\n\t\ttop : 5,\r\n\t\tleft : 65\r\n\t});\r\n\r\n\trowView.add(avaLabel);\r\n\r\n\tvar imgThingy = Titanium.UI.createImageView({\r\n\t\timage : 'http://placekitten.com/g/300/200',\r\n\t\theight : 200,\r\n\t\twidth : 300\r\n\t});\r\n\r\n\trowView.add(imgThingy);\r\n\r\n\tvar postTitle = Ti.UI.createLabel({\r\n\t\ttext : \"Cat saves the day\",\r\n\t\tfont : {\r\n\t\t\tfontSize : 18,\r\n\t\t\tfontWeight : 'bold'\r\n\t\t}\r\n\t});\r\n\r\n\trowView.add(postTitle);\r\n\r\n\tvar postText = Ti.UI.createLabel({\r\n\t\ttext : \"At 12, a helicopter crashed and all passengers were saved by this cat\",\r\n\t\tfont : {\r\n\t\t\tfontSize : 10,\r\n\t\t}\r\n\t});\r\n\r\n\trowView.add(postText);\r\n\t\r\n\treturn rowView;\r\n}\r\n\r\nvar buildTable = function() {\r\n\tvar data = [];\r\n\tvar table = Ti.UI.createTableView({\r\n\t\ttop : 0,\r\n\t\tright : 0,\r\n\t\tbottom : 0,\r\n\t\tleft : 0\r\n\t});\r\n\r\n\tfor (var i = 0; i < 5; i++) {\r\n\t\tdata.push(buildRow());\r\n\t}\r\n\r\n\ttable.setData(data);\r\n\r\n\ttable.addEventListener('scroll', function(e) {\r\n\t\tif (e.contentOffset.y + e.size.height + 100 > e.contentSize.height) {\r\n\t\t\ttable.appendRow(buildRow());\r\n\t\t\ttable.appendRow(buildRow());\r\n\t\t\ttable.appendRow(buildRow());\r\n\t\t\ttable.appendRow(buildRow());\r\n\t\t\ttable.appendRow(buildRow());\r\n\t\t}\r\n\t});\r\n\r\n\treturn table;\r\n}\r\n\r\nvar win = Ti.UI.createWindow({\r\n\tbackgroundColor : '#fff'\r\n});\r\n\r\nvar table = buildTable();\r\n\r\nwin.add(table);\r\n\r\nwin.open(); \r\n\r\n{code}\r\n", "attachment": [], "flagged": false, "summary": "iOS: Table view scrolling lags/freezes when dynamically adding rows", "creator": { "name": "btran", "key": "btran", "displayName": "Betty Tran", "active": true, "timeZone": "America/Los_Angeles" }, "subtasks": [], "reporter": { "name": "btran", "key": "btran", "displayName": "Betty Tran", "active": true, "timeZone": "America/Los_Angeles" }, "environment": "Tested on Titanium SDK 2.0.2 & 2.0.1GA2 \r\niphone 4 & 3GS", "comment": { "comments": [ { "id": "199246", "author": { "name": "vduggal", "key": "vduggal", "displayName": "Vishal Duggal", "active": false, "timeZone": "America/Los_Angeles" }, "body": "Trying to update a tableView while it is scrolling will result in lags/freezes and generally jerky behavior. That is because you have two competing processes running alternately on the main thread.\r\n\r\nWould advise that tableView update not be done on the scroll event but instead on a explicit user action. You can use either the headerPullView (See KS for an example) or the footerView properties of the table. Attaching example for footerView\r\n\r\n{code}\r\nvar buildRow = function() {\r\n var rowView = Titanium.UI.createTableViewRow({\r\n className : 'lolcat',\r\n layout : \"vertical\",\r\n height : 350,\r\n backgroundColor : 'pink'\r\n });\r\n \r\n var w1 = Math.round(Math.random()*100+50);\r\n var w2 = Math.round(Math.random()*100+300);\r\n \t\r\n var imgAvatar = Titanium.UI.createImageView({\r\n //image : 'http://placekitten.com/g/50/50',\r\n image : 'http://placekitten.com/g/'+w1+'/'+w1,\r\n height : 50,\r\n width : 50,\r\n top : 5,\r\n left : 5\r\n });\r\n \r\n rowView.add(imgAvatar);\r\n \r\n var avaLabel = Ti.UI.createLabel({\r\n text : \"Super Cat\",\r\n font : {\r\n fontSize : 12,\r\n fontWeight : 'bold'\r\n },\r\n top : 5,\r\n left : 65\r\n });\r\n \r\n rowView.add(avaLabel);\r\n \r\n var imgThingy = Titanium.UI.createImageView({\r\n //image : 'http://placekitten.com/g/300/200',\r\n image : 'http://placekitten.com/g/'+w2+'/'+w2,\r\n height : 200,\r\n width : 300\r\n });\r\n \r\n rowView.add(imgThingy);\r\n \r\n var postTitle = Ti.UI.createLabel({\r\n text : \"Cat saves the day\",\r\n font : {\r\n fontSize : 18,\r\n fontWeight : 'bold'\r\n }\r\n });\r\n \r\n rowView.add(postTitle);\r\n \r\n var postText = Ti.UI.createLabel({\r\n text : \"At 12, a helicopter crashed and all passengers were saved by this cat\",\r\n font : {\r\n fontSize : 10,\r\n }\r\n });\r\n \r\n rowView.add(postText);\r\n \r\n return rowView;\r\n}\r\n \r\nvar buildTable = function() {\r\n var data = [];\r\n var table = Ti.UI.createTableView({\r\n top : 0,\r\n right : 0,\r\n bottom : 0,\r\n left : 0\r\n });\r\n \r\n for (var i = 0; i < 5; i++) {\r\n data.push(buildRow());\r\n }\r\n \r\n table.setData(data);\r\n \r\n var footerView = Ti.UI.createView({\r\n \twidth:Ti.UI.FILL,\r\n \theight:Ti.UI.SIZE\r\n });\r\n var button = Ti.UI.createButton({\r\n \twidth:Ti.UI.FILL,\r\n \theight:Ti.UI.SIZE,\r\n \ttitle:'Load More Data'\r\n })\r\n footerView.add(button);\r\n \r\n button.addEventListener('click',function(e){\r\n table.appendRow(buildRow());\r\n table.appendRow(buildRow());\r\n table.appendRow(buildRow());\r\n table.appendRow(buildRow());\r\n table.appendRow(buildRow());\r\n })\r\n \r\n table.footerView = footerView;\r\n \r\n return table;\r\n}\r\n \r\nvar win = Ti.UI.createWindow({\r\n backgroundColor : '#fff'\r\n});\r\n \r\nvar table = buildTable();\r\n \r\nwin.add(table);\r\n \r\nwin.open(); \r\n{code}", "updateAuthor": { "name": "vduggal", "key": "vduggal", "displayName": "Vishal Duggal", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2012-06-19T16:24:07.000+0000", "updated": "2012-06-19T16:24:07.000+0000" }, { "id": "264672", "author": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "body": "I suggest this issue to be re-opened. Automatically loading more rows while scrolling is a very common concept, that should be supported in Titanium.", "updateAuthor": { "name": "fokkezb", "key": "fokke", "displayName": "Fokke Zandbergen", "active": true, "timeZone": "Europe/Amsterdam" }, "created": "2013-08-02T13:36:39.000+0000", "updated": "2013-08-02T13:36:39.000+0000" }, { "id": "285954", "author": { "name": "sameeh.harfoush", "key": "sameeh.harfoush", "displayName": "Sameeh Harfoush ", "active": true, "timeZone": "Asia/Beirut" }, "updateAuthor": { "name": "sameeh.harfoush", "key": "sameeh.harfoush", "displayName": "Sameeh Harfoush ", "active": true, "timeZone": "Asia/Beirut" }, "created": "2013-12-27T17:33:07.000+0000", "updated": "2013-12-27T17:33:07.000+0000" }, { "id": "285982", "author": { "name": "aleard", "key": "aleard", "displayName": "Alan Leard", "active": true, "timeZone": "America/Los_Angeles" }, "body": "ListView handles this very well on both platforms. Please review the guide documentation here and compare your results: http://docs.appcelerator.com/titanium/latest/#!/guide/ListViews", "updateAuthor": { "name": "aleard", "key": "aleard", "displayName": "Alan Leard", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-12-27T19:49:17.000+0000", "updated": "2013-12-27T19:49:17.000+0000" }, { "id": "286005", "author": { "name": "sameeh.harfoush", "key": "sameeh.harfoush", "displayName": "Sameeh Harfoush ", "active": true, "timeZone": "Asia/Beirut" }, "body": "well i am still figuring out how to create the template and subtemplates to fit my data-model. the thing is that every single feed contains views that are created by calling other classes (modular) that create the necessary view UI. for example, the main container view contains four types of UI: first UI for the user, second one is for a business, third is for voting...etc. the data model is a bit complicated to map on a listview template, so listview is not feasible solution at this point...i still don't understand why a screen can render on Android and not on iPhone? is is a native UI limitation for iOS?", "updateAuthor": { "name": "sameeh.harfoush", "key": "sameeh.harfoush", "displayName": "Sameeh Harfoush ", "active": true, "timeZone": "Asia/Beirut" }, "created": "2013-12-27T20:52:59.000+0000", "updated": "2013-12-27T20:52:59.000+0000" }, { "id": "420727", "author": { "name": "lmorris", "key": "lmorris", "displayName": "Lee Morris", "active": false, "timeZone": "America/Los_Angeles" }, "body": "Closing ticket as invalid.", "updateAuthor": { "name": "lmorris", "key": "lmorris", "displayName": "Lee Morris", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2017-05-31T22:37:09.000+0000", "updated": "2017-05-31T22:37:09.000+0000" } ], "maxResults": 8, "total": 8, "startAt": 0 } } }