{ "id": "163353", "key": "TIMOB-23934", "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": [ { "id": "17608", "name": "Release 6.1.0", "archived": false, "released": true, "releaseDate": "2017-05-26" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2016-09-27T04:47:24.000+0000", "created": "2016-09-21T09:26:11.000+0000", "priority": { "name": "Critical", "id": "1" }, "labels": [ "children", "clickevent", "ios", "run-on-main-thread" ], "versions": [ { "id": "17706", "name": "Release 5.4.0", "archived": false, "released": true, "releaseDate": "2016-08-11" }, { "id": "18253", "name": "Release 5.5.0", "archived": false, "released": true, "releaseDate": "2016-09-13" } ], "issuelinks": [ { "id": "54703", "type": { "id": "10002", "name": "Duplicate", "inward": "is duplicated by", "outward": "duplicates" }, "inwardIssue": { "id": "167077", "key": "TIMOB-24573", "fields": { "summary": "[iOS] View inside another view does not fire events", "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" } }, "priority": { "name": "Critical", "id": "1" }, "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false } } } } ], "assignee": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "updated": "2017-04-12T15:18:50.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": "Scenario : \r\n\r\n- *Tableview* with n *TableViewRow*\r\n- Every TableViewRow has a *view container*\r\n- Every view container has n children (label / view)\r\n\r\nProblem : \r\n\r\n- Only the first children of the view container doesn't fire the *touchstart* event , but fire the *click* event. All the other children fire touchstart and click event. Try to enabled the code commented , and disabled the code just above. \r\n\r\nI edited an example found on the doc\r\n\r\n{code}\r\nTi.UI.setBackgroundColor('#000');\r\nvar win = Ti.UI.createWindow({\r\n backgroundColor: 'black',\r\n exitOnClose: true,\r\n fullscreen: false,\r\n title: 'TableView Demo'\r\n});\r\n\r\n// generate random number, used to make each row appear distinct for this example\r\nfunction randomInt(max){\r\n return Math.floor(Math.random() * max) + 1;\r\n}\r\n\r\nvar IMG_BASE = 'https://github.com/appcelerator/titanium_mobile/raw/master/demos/KitchenSink/Resources/images/';\r\nvar defaultFontSize = Ti.Platform.name === 'android' ? 16 : 14;\r\n\r\nvar tableData = [];\r\n\r\nfor (var i=1; i<=20; i++){\r\n\t \r\n\t var row = Ti.UI.createTableViewRow({\r\n\t className:'forumEvent', // used to improve table performance\r\n\t selectedBackgroundColor:'white',\r\n\t rowIndex:i, // custom property, useful for determining the row during events\r\n\t height:110\r\n\t });\r\n\t\r\n\t var testView = Ti.UI.createView({\r\n\t \twidth : Ti.UI.FILL,\r\n\t \theight : Ti.UI.FILL\r\n\t });\r\n\t \r\n\t testView.addEventListener(\"touchstart\" , function(){\r\n\t \tTi.API.info(\"touchstart event\");\r\n\t });\r\n\t testView.addEventListener(\"click\" , function(){\r\n\t \tTi.API.info(\"click event\");\r\n\t });\r\n\t \r\n\t var imageAvatar = Ti.UI.createImageView({\r\n\t image: IMG_BASE + 'custom_tableview/user.png',\r\n\t left:10, top:5,\r\n\t width:50, height:50,\r\n\t borderColor : \"red\"\r\n\t });\r\n\r\n\t var labelUserName = Ti.UI.createLabel({\r\n\t color:'#576996',\r\n\t font:{fontFamily:'Arial', fontSize:defaultFontSize+6, fontWeight:'bold'},\r\n\t text:'Fred Smith ' + i,\r\n\t left:70, top: 6,\r\n\t width:200, height: 30,\r\n\t borderColor : \"red\"\r\n\t });\r\n\t \r\n\t\r\n\t var labelDetails = Ti.UI.createLabel({\r\n\t color:'#222',\r\n\t font:{fontFamily:'Arial', fontSize:defaultFontSize+2, fontWeight:'normal'},\r\n\t text:'Replied to post with id ' + randomInt(1000) + '.',\r\n\t left:70, top:44,\r\n\t width:360,\r\n\t borderColor : \"red\"\r\n\t });\r\n\t \r\n\t\r\n\t var imageCalendar = Ti.UI.createImageView({\r\n\t image:IMG_BASE + 'custom_tableview/eventsButton.png',\r\n\t left:70, bottom: 2,\r\n\t width:32, height: 32,\r\n\t borderColor : \"red\"\r\n\t });\r\n\t \r\n\t\r\n\t var labelDate = Ti.UI.createLabel({\r\n\t color:'#999',\r\n\t font:{fontFamily:'Arial', fontSize:defaultFontSize, fontWeight:'normal'},\r\n\t text:'on ' + randomInt(30) + ' Nov 2012',\r\n\t left:105, bottom:10,\r\n\t width:200, height:20,\r\n\t borderColor : \"red\"\r\n\t });\r\n\t \r\n\t \r\n\t //imageAvatar not fire touchstart event\r\n\t testView.add(imageAvatar);\r\n\t testView.add(labelUserName);\r\n\t testView.add(labelDetails);\r\n\t testView.add(imageCalendar);\r\n\t testView.add(labelDate);\r\n\t \r\n\t //labelUserName not fire touchstart event\r\n\t /*testView.add(labelUserName);\r\n\t testView.add(imageAvatar);\r\n\t testView.add(labelDetails);\r\n\t testView.add(imageCalendar);\r\n\t testView.add(labelDate);*/\r\n\r\n\t \r\n\t row.add(testView);\r\n\t tableData.push(row);\r\n}\r\n\r\nvar tableView = Ti.UI.createTableView({\r\n backgroundColor:'white',\r\n data:tableData\r\n});\r\n\r\nwin.add(tableView);\r\nwin.open();\r\n{code}\r\n", "attachment": [ { "id": "60300", "filename": "test.mov", "author": { "name": "nicolomonili", "key": "nicolomonili", "displayName": "nicolomonili", "active": true, "timeZone": "Europe/Rome" }, "created": "2016-09-21T09:32:16.000+0000", "size": 5634196, "mimeType": "video/quicktime" } ], "flagged": false, "summary": "iOS: The first view-children not firing click-events when using run-on-main-thread", "creator": { "name": "nicolomonili", "key": "nicolomonili", "displayName": "nicolomonili", "active": true, "timeZone": "Europe/Rome" }, "subtasks": [], "reporter": { "name": "nicolomonili", "key": "nicolomonili", "displayName": "nicolomonili", "active": true, "timeZone": "Europe/Rome" }, "environment": "Appcelerator Studio, build: 4.3.3.201510212245\r\nSDK 5.5.0.G.A\r\nxCode 8 iOS 10 , tested on iPhone Simulator", "closedSprints": [ { "id": 722, "state": "closed", "name": "2016 Sprint 20 SDK", "startDate": "2016-09-28T16:50:17.299Z", "endDate": "2016-10-12T16:50:00.000Z", "completeDate": "2016-10-10T06:17:01.016Z", "originBoardId": 114 } ], "comment": { "comments": [ { "id": "396806", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "Looks like an issue with the {{Ti.UI.ImageView}} component. Does it only happen when being children inside a TableView or also for independent image-views?", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-09-21T09:58:54.000+0000", "updated": "2016-09-21T09:58:54.000+0000" }, { "id": "396808", "author": { "name": "nicolomonili", "key": "nicolomonili", "displayName": "nicolomonili", "active": true, "timeZone": "Europe/Rome" }, "body": "Is not an Imageview problem.\r\n\r\ntry to uncomment this\r\n {code}\r\n//labelUserName not fire touchstart event\r\n/*testView.add(labelUserName);\r\ntestView.add(imageAvatar);\r\ntestView.add(labelDetails);\r\ntestView.add(imageCalendar);\r\ntestView.add(labelDate);*/\r\n {code}\r\nand comment this \r\n {code}\r\n//imageAvatar not fire touchstart event\r\ntestView.add(imageAvatar);\r\ntestView.add(labelUserName);\r\ntestView.add(labelDetails);\r\ntestView.add(imageCalendar);\r\ntestView.add(labelDate);\r\n {code}\r\nlabelUserName is a label , and have the problem", "updateAuthor": { "name": "nicolomonili", "key": "nicolomonili", "displayName": "nicolomonili", "active": true, "timeZone": "Europe/Rome" }, "created": "2016-09-21T10:05:03.000+0000", "updated": "2016-09-21T10:05:03.000+0000" }, { "id": "396810", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "Alright, even better to know. Might some some index-issue then. Will move it to TIMOB as it's a valid issue.", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-09-21T10:06:59.000+0000", "updated": "2016-09-21T10:06:59.000+0000" }, { "id": "396812", "author": { "name": "nicolomonili", "key": "nicolomonili", "displayName": "nicolomonili", "active": true, "timeZone": "Europe/Rome" }, "body": "The problem is very serious .\r\nThere is also the problem with n view inside a main view.\r\nThe first child of the main view not fire any event! \r\n\r\n{code}\r\nvar win = Ti.UI.createWindow({\r\n backgroundColor: 'black'\r\n});\r\n\r\nvar viewTest = Ti.UI.createView({\r\n\twidth : 200,\r\n\theight : 200,\r\n\tbackgroundColor : \"red\",\r\n\ttop : 5\r\n});\r\nviewTest.addEventListener(\"touchstart\" , function(e){\r\n\tTi.API.info(\"touchstart viewTest\");\r\n});\r\nviewTest.addEventListener(\"click\" , function(e){\r\n\tTi.API.info(\"click viewTest\");\r\n});\r\n\r\nvar viewTest1 = Ti.UI.createView({\r\n\twidth : 50,\r\n\theight : 50,\r\n\tbackgroundColor : \"blue\",\r\n\tleft : 10\r\n});\r\n\r\n\r\nvar viewTest2 = Ti.UI.createView({\r\n\twidth : 50,\r\n\theight : 50,\r\n\tbackgroundColor : \"green\",\r\n\tright : 10\r\n});\r\n\r\nviewTest.add(viewTest1,viewTest2);\r\nwin.add(viewTest);\r\nwin.open();\r\n{code}\r\n\r\n", "updateAuthor": { "name": "nicolomonili", "key": "nicolomonili", "displayName": "nicolomonili", "active": true, "timeZone": "Europe/Rome" }, "created": "2016-09-21T10:44:36.000+0000", "updated": "2016-09-21T10:45:19.000+0000" }, { "id": "396813", "author": { "name": "nicolomonili", "key": "nicolomonili", "displayName": "nicolomonili", "active": true, "timeZone": "Europe/Rome" }, "body": "i can't edit the ticket\r\ni have to upload another video test for the second case of the problem", "updateAuthor": { "name": "nicolomonili", "key": "nicolomonili", "displayName": "nicolomonili", "active": true, "timeZone": "Europe/Rome" }, "created": "2016-09-21T10:49:09.000+0000", "updated": "2016-09-21T11:05:28.000+0000" }, { "id": "396816", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "I noticed somethine really interesting: If you add the event-listeners after the child-views have been added, everything works well. Investigating ...\r\n\r\n*EDIT*: This is a {{run-on-main-thread}} issue! Disabling it in the tiapp fixes the issue. Will investigate in that direction.", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-09-21T12:31:20.000+0000", "updated": "2016-09-21T12:35:16.000+0000" }, { "id": "396817", "author": { "name": "nicolomonili", "key": "nicolomonili", "displayName": "nicolomonili", "active": true, "timeZone": "Europe/Rome" }, "body": "Ok with the property set to false the problem is fix.\r\nThere is some difference if i put the property false ?", "updateAuthor": { "name": "nicolomonili", "key": "nicolomonili", "displayName": "nicolomonili", "active": true, "timeZone": "Europe/Rome" }, "created": "2016-09-21T12:39:58.000+0000", "updated": "2016-09-21T12:46:46.000+0000" }, { "id": "397182", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "You need the flag for running Hyperloop, so we need to fix it anyway. It is scheduled for the next release 6.0.0 now.", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-09-25T12:39:32.000+0000", "updated": "2016-09-25T12:39:32.000+0000" }, { "id": "397183", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "*Some further investigations*:\r\n- The issue is only happening when having {{run-on-main-thread}} enabled in the tiapp.xml\r\n- The issue is only happening to the very first child of the vier-hierarchy\r\n- The issue is not happening when assigning the click-events to the child-views directly\r\n- The issue is not happening when the event-listener is added to the view after the child-views have been added\r\n- Adding an empty \"layer-view\" that acts as the first child fixes the issue for all other views (hack / workaround)\r\n\r\n[~cng] I may need a second pair of eyes on this one. It must be some missing {{#ifdef TI_USE_KROLL_THREAD}} somewhere to wrap a certain {{lock}}/{{unlock}}.", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-09-25T12:43:17.000+0000", "updated": "2016-09-25T12:43:17.000+0000" }, { "id": "397213", "author": { "name": "cng", "key": "cng", "displayName": "Chee Kiat Ng", "active": false, "timeZone": "America/Los_Angeles" }, "body": "[~hansknoechel] Just briefly checked but, it looks like the difference is affected here on TiViewProxy.m:\r\nhttps://github.com/appcelerator/titanium_mobile/blob/master/iphone/Classes/TiViewProxy.m#L224 to L245 is executed if *run-on-main-thread*.\r\nhttps://github.com/appcelerator/titanium_mobile/blob/master/iphone/Classes/TiViewProxy.m#L255 to L267 is executed if NOT *run-on-main-thread*.\r\n\r\nIf you observe both chunks of code closely, there's only subtle differences. In fact, I hacked a little and commented out:\r\nhttps://github.com/appcelerator/titanium_mobile/blob/master/iphone/Classes/TiViewProxy.m#L230\r\nThe issue is solved when *run-on-main-thread*.\r\n\r\nHope that helps.", "updateAuthor": { "name": "cng", "key": "cng", "displayName": "Chee Kiat Ng", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2016-09-26T06:39:57.000+0000", "updated": "2016-09-26T06:39:57.000+0000" }, { "id": "397214", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "That helps greatly, thanks! Will take a closer look today.", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-09-26T07:02:03.000+0000", "updated": "2016-09-26T07:02:03.000+0000" }, { "id": "397235", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "Here is the problem:\r\n{code:objc}\r\npthread_rwlock_wrlock(&childrenLock);\r\nif(position < 0 || position > [children count]) {\r\n position = (int)[children count];\r\n}\r\n[children insertObject:childView atIndex:position];\r\n//Turn on clipping because I have child\r\n[[self view] updateClipping];\r\npthread_rwlock_unlock(&childrenLock);\r\n{code}\r\nIn this example, for the first child, the {{position}} is {{nil}} instead of {{0}} (for the child-index of the parent). The next view that is added received the correct index (1) and therefore works. So the locks some kind of lose the value of the {{position}} property. Investigating in that direction.", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-09-26T13:36:49.000+0000", "updated": "2016-09-26T13:37:11.000+0000" }, { "id": "397236", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "So basically what I came up with now is that the threading / read-write-lock caused the problems on the main-thread. I solved the issue by moving the (UI-related) clipping outside the lock that is used to define a unique position. It is necessary to keep this lock to prevent certain race-conditions that can occur. \r\n\r\nIt looks like a solid solution to me and makes sense, since the clipping is not UI-thread related and should therefore not be blocked by the read-write-lock. Please take the below demo-code as well as our KitchenSink to test the general behavior of this PR. It is a *very* affective PR and should be well-tested before merging. \r\n\r\nPR: https://github.com/appcelerator/titanium_mobile/pull/8432\r\n\r\nDemo (adjusted from above):\r\n{code:javascript}\r\nvar win = Ti.UI.createWindow({\r\n backgroundColor: 'black'\r\n});\r\n\r\nvar viewTest = Ti.UI.createView({\r\n width: 200,\r\n height: 200,\r\n backgroundColor: \"red\",\r\n top: 5\r\n});\r\n\r\nviewTest.addEventListener(\"touchstart\", function(e) {\r\n Ti.API.info(\"touchstart viewTest\");\r\n});\r\n\r\nviewTest.addEventListener(\"click\", function(e) {\r\n Ti.API.info(\"click viewTest\");\r\n});\r\n\r\nvar viewTest1 = Ti.UI.createView({\r\n width: 50,\r\n height: 50,\r\n backgroundColor: \"blue\",\r\n left: 10\r\n});\r\n\r\n\r\nvar viewTest2 = Ti.UI.createView({\r\n width: 50,\r\n height: 50,\r\n backgroundColor: \"green\",\r\n right: 10\r\n});\r\n\r\nviewTest.add(viewTest1);\r\nviewTest.add(viewTest2);\r\n\r\nwin.add(viewTest);\r\nwin.open();\r\n{code}", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-09-26T14:12:48.000+0000", "updated": "2016-09-26T14:12:48.000+0000" }, { "id": "397349", "author": { "name": "cng", "key": "cng", "displayName": "Chee Kiat Ng", "active": false, "timeZone": "America/Los_Angeles" }, "body": "CR and FT passed. Tested on earlier reporter sample code as well. Tested on KitchenSink various events tests as well.", "updateAuthor": { "name": "cng", "key": "cng", "displayName": "Chee Kiat Ng", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2016-09-27T04:46:59.000+0000", "updated": "2016-09-27T04:46:59.000+0000" }, { "id": "401362", "author": { "name": "htbryant", "key": "htbryant", "displayName": "Harry Bryant", "active": true, "timeZone": "Europe/London" }, "body": "Verified as fixed, Tested the reporter's sample code, the sample code provided by [~hansknoechel] as well as related test suites in KitchenSink such as Table Views, zIndex & Events Interaction. Tested on Sim and Device.\r\n\r\nTested On:\r\niPhone 6 Plus 10.1.1 Device & Simulator\r\nMac OS Sierra (10.12.1)\r\nTi SDK: 6.1.0.v20161116071014\r\nAppc Studio: 4.8.0.201611121409\r\nAppc NPM: 4.2.8\r\nApp CLI: 6.1.0-14\r\nXcode 8.1\r\nNode v4.4.7\r\n\r\n*Closing ticket.*", "updateAuthor": { "name": "htbryant", "key": "htbryant", "displayName": "Harry Bryant", "active": true, "timeZone": "Europe/London" }, "created": "2016-11-17T17:06:47.000+0000", "updated": "2016-11-17T17:06:47.000+0000" } ], "maxResults": 15, "total": 15, "startAt": 0 } } }