{ "id": "111448", "key": "TIMOB-13162", "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": "15564", "description": "2013 Sprint 15 API", "name": "2013 Sprint 15 API", "archived": true, "released": true, "releaseDate": "2013-07-29" }, { "id": "15567", "description": "2013 Sprint 15", "name": "2013 Sprint 15", "archived": true, "released": true, "releaseDate": "2013-07-29" }, { "id": "14982", "description": "Release 3.2.0", "name": "Release 3.2.0", "archived": false, "released": true, "releaseDate": "2013-12-19" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2013-07-20T23:02:45.000+0000", "created": "2013-03-20T12:07:07.000+0000", "priority": null, "labels": [ "exalture", "qe-closed-3.2.0" ], "versions": [], "issuelinks": [], "assignee": { "name": "ingo", "key": "ingo", "displayName": "Ingo Muschenetz", "active": true, "timeZone": "America/Los_Angeles" }, "updated": "2013-12-17T01:29:28.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": "When I assign a function to titanium proxy object property it usually works ok. But in some cases accessing this property later on returns different object.\r\n{noformat}\r\nvar view = Ti.UI.createView();\r\nvar properties = {}\r\nview.prop = function (attr, value) {\r\n if (arguments.length == 1) {\r\n return properties[arguments[0]]\r\n } else {\r\n properties[arguments[0]] = arguments[1]\r\n }\r\n}\r\n\r\n//later on\r\n\r\nview.prop('someVal') //fails with error because view.prop return some non callable object or another, totally unrelated, JS function.\r\n{noformat}\r\n\r\nAfter some research I've found that view.prop is represented as a KrollWrapper instance with jsobject instance variable referencing my JS function. And there is nothing stopping JS runtime from garbadge collecting this jsobject which happens in some cases.\r\n\r\nBTW above code helps to attach complex objects to proxies without performance penalty for copying values from JS to iOS and vice versa. A proxy store reference to a JS function (which is cheap) and JS function deals with state inside JS runtime without any copying.", "attachment": [], "flagged": false, "summary": "iOS: Functions assigned to proxy property may be garbage collected", "creator": { "name": "andrey@studiomobile.ru", "key": "andrey@studiomobile.ru", "displayName": "Andrey Verbin", "active": true, "timeZone": "America/Los_Angeles" }, "subtasks": [], "reporter": { "name": "andrey@studiomobile.ru", "key": "andrey@studiomobile.ru", "displayName": "Andrey Verbin", "active": true, "timeZone": "America/Los_Angeles" }, "environment": "iOS Simulator 5.1\r\nTitanium: 07dccb60d0ae048399cc6f174502a872b9da1fa9", "comment": { "comments": [ { "id": "243144", "author": { "name": "dcassenti", "key": "dcassenti", "displayName": "Davide Cassenti", "active": true, "timeZone": "Europe/Berlin" }, "body": "Assigning properties to Proxies is always not recommended; do you have any particular reason you want to do that? The approach should be having a wrapping object:\n\n{code}\nvar MyView = {\n view: Ti.UI.createView(),\n properties: []\n}\n{code}", "updateAuthor": { "name": "dcassenti", "key": "dcassenti", "displayName": "Davide Cassenti", "active": true, "timeZone": "Europe/Berlin" }, "created": "2013-03-20T14:43:55.000+0000", "updated": "2013-03-20T14:43:55.000+0000" }, { "id": "243365", "author": { "name": "andrey@studiomobile.ru", "key": "andrey@studiomobile.ru", "displayName": "Andrey Verbin", "active": true, "timeZone": "America/Los_Angeles" }, "body": "I'm creating a databinding framework for Titanium. Binding procedure traverse view hierachy and set view properties based on binding information attached to every view. Super simplified version of my code looks like this:\n{noformat}\nfunction applyBindngs(root) {\n for (var i = 0; i < root.children.length; ++i) {\n var view = root.children[i];\n var bindingInfo = view.prop(\"bindings\");\n //complicated data binding logic here\n appyBinding(view);\n }\n}\n{noformat}\nIt is very convenient to have proxy object as input since it already have links to all subviews.\nIf I would do it with wrappers I would need to create parallel hierarchy of wrapper objects and traverse it. Something like this:\n{noformat}\nvar Wrapper = {\n view : Ti.UI.createView(),\n children : [],\n add : function (child) {\n children.push(child);\n view.add(chid.view);\n },\n bindingInfo : {},\n}\nfunction applyBindngs(rootWrapper) {\n for (var i = 0; i < rootWrapper.children.length; ++i) {\n var wrapper = rootWrapper.children[i];\n var bindingInfo = wrapper.bindings;\n var view = wrapper.view;\n //complicated data binding logic here\n appyBinding(wrapper);\n }\n}\n{noformat}\nWhile above approach valid and follows Appcelerator recommendations it also requires parallel hierarchy of wrapper objects and force all view related code access views through wrappers. This is very fragile since a line like this would break everything:\n{noformat}\nwrapper.view.add(Ti.UI.createView())\n{noformat}\n\nWhile this is my particular situation, same problems are true for any code that process view hierarchy in a generic fashion and requires some additional information associated with views to work.\n\nI ended up with \"prop\" function because with it I can avoid marshaling JS objects to their native representations (NSString, NSDictionary, etc). Ideally marshaling should only happen when JS objects passed as arguments to TiUIView methods. When JS objects attached to a proxy they should be saved as reference to native JS object inside a proxy without any marshaling. ", "updateAuthor": { "name": "andrey@studiomobile.ru", "key": "andrey@studiomobile.ru", "displayName": "Andrey Verbin", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-03-21T09:02:20.000+0000", "updated": "2013-03-21T09:02:20.000+0000" }, { "id": "262571", "author": { "name": "srahim", "key": "srahim", "displayName": "Sabil Rahim", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Fixed by https://github.com/appcelerator/titanium_mobile/pull/3994", "updateAuthor": { "name": "srahim", "key": "srahim", "displayName": "Sabil Rahim", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2013-07-20T23:02:23.000+0000", "updated": "2013-07-20T23:02:23.000+0000" }, { "id": "284646", "author": { "name": "wluu", "key": "wluu", "displayName": "Wilson Luu", "active": false, "timeZone": "America/Los_Angeles" }, "body": "Closing ticket as fixed. Verified functions assigned to the proxy property will not be garbage collected. \n\nBelow is the reproducible steps:\n\n1. Create a Titanium app with the following code:\n{code:title=app.js}\nvar view = Ti.UI.createView();\nview.prop = function (value) {\n \tTi.API.info(\"I got called\");\n};\n \nvar button = Ti.UI.createButton({\n\ttitle:'button'\n});\n\nbutton.addEventListener('click', function(){\n\tview.prop('someVal');\t\n});\n \n\nvar window = Ti.UI.createWindow({backgroundColor:\"green\"});\n\nwindow.add(button);\nwindow.open();\n{code}\n\n2. Install app to an iOS simulator with trace on; was able to reproduce the fail case in 3.1.3 GA stack with Xcode 5.0.2 *only with* iOS simulator 7.0.3 and 6.1\n3. Once simulator is launched and app is launched, go to Hardware > Simulate Memory Warning\n4. You should see this message in the Studio console: [DEBUG] : 2013-12-16 17:25:42.359 monkey13162[34784:a07] Received memory warning.\n5. Next, press the button on the app\n6. You should see this message in the Studio console: [INFO] : I got called\n\nTested on:\n\nAppcelerator Studio, build: 3.2.0.201312151544\nSDK build: 3.2.0.v20131216064236\nCLI: 3.2.0-cr3\nAlloy: 1.3.0-cr\nXcode: 5.0.2\nDevice: iphone simulator with retina (7.0.3), iphone simulator with retina (6.1)\n", "updateAuthor": { "name": "wluu", "key": "wluu", "displayName": "Wilson Luu", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2013-12-17T01:28:52.000+0000", "updated": "2013-12-17T01:28:52.000+0000" } ], "maxResults": 4, "total": 4, "startAt": 0 } } }