{ "id": "176255", "key": "AC-6712", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "12217", "key": "AC", "name": "Appcelerator - INBOX", "projectCategory": { "id": "10000", "description": "", "name": "Customer Service" } }, "resolution": { "id": "11", "description": "Is not a bug in our product", "name": "Not Our Bug" }, "resolutiondate": "2021-08-05T14:23:43.000+0000", "created": "2021-07-20T13:04:40.000+0000", "labels": [ "crash", "ios" ], "versions": [], "issuelinks": [], "assignee": { "name": "amukherjee", "key": "amukherjee", "displayName": "Abir Mukherjee", "active": true, "timeZone": "America/Los_Angeles" }, "updated": "2021-08-05T14:23:43.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": "14548", "name": "Titanium SDK & CLI", "description": "Please enter tickets related to the MobileSDK here." } ], "description": "Opening a webdialog triggered by a button event listener after you've opened and closed it causes a crash on iOS. On Android everything works correctly (and the Dialog opens again and again when required).\r\n\r\nAttached, you can find two different crash logs for the same problem.\r\n\r\nThe source code of the app is on: https://github.com/ferdi2005/monumenti\r\n\r\nThe involved controller is upload/config and the button has the id login_start. \r\n\r\n{code}\r\n[DEBUG] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally a view controller that is already being presented by .'\r\n[DEBUG] *** First throw call stack:\r\n[DEBUG] (\r\n[DEBUG] 0 CoreFoundation 0x00000001124e7fba __exceptionPreprocess + 242\r\n[DEBUG] 1 libobjc.A.dylib 0x000000011208dff5 objc_exception_throw + 48\r\n[DEBUG] 2 UIKitCore 0x000000012105df32 -[UIViewController _presentViewController:withAnimationController:completion:] + 6016\r\n[DEBUG] 3 UIKitCore 0x000000012105e93c __63-[UIViewController _presentViewController:animated:completion:]_block_invoke + 98\r\n[DEBUG] 4 UIKitCore 0x000000012107949c -[_UIViewControllerTransitionCoordinator _applyBlocks:releaseBlocks:] + 294\r\n[DEBUG] 5 UIKitCore 0x000000012107570e -[_UIViewControllerTransitionContext _runAlongsideCompletions] + 126\r\n[DEBUG] 6 UIKitCore 0x0000000121075482 -[_UIViewControllerTransitionContext completeTransition:] + 106\r\n[DEBUG] 7 SafariServices 0x000000010db79007 __60-[SFInteractiveDismissController _presentAnimateTransition:]_block_invoke_2 + 39\r\n[DEBUG] 8 UIKitCore 0x0000000121cd1e7a -[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:] + 779\r\n[DEBUG] 9 UIKitCore 0x0000000121ca2831 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 231\r\n[DEBUG] 10 UIKitCore 0x0000000121ca2dd6 -[UIViewAnimationState animationDidStop:finished:] + 263\r\n[DEBUG] 11 UIKitCore 0x0000000121ca2f57 -[UIViewAnimationState animationDidStop:finished:] + 648\r\n[DEBUG] 12 QuartzCore 0x000000011127ddc0 _ZN2CA5Layer23run_animation_callbacksEPv + 308\r\n[DEBUG] 13 libdispatch.dylib 0x000000011622e8df _dispatch_client_callout + 8\r\n[DEBUG] 14 libdispatch.dylib 0x000000011623ba27 _dispatch_main_queue_callback_4CF + 1045\r\n[DEBUG] 15 CoreFoundation 0x00000001124558f8 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9\r\n[DEBUG] 16 CoreFoundation 0x0000000112450169 __CFRunLoopRun + 2781\r\n[DEBUG] 17 CoreFoundation 0x000000011244f1a7 CFRunLoopRunSpecific + 567\r\n[DEBUG] 18 GraphicsServices 0x0000000125b8fd85 GSEventRunModal + 139\r\n[DEBUG] 19 UIKitCore 0x00000001217864df -[UIApplication _run] + 912\r\n[DEBUG] 20 UIKitCore 0x000000012178b39c UIApplicationMain + 101\r\n[DEBUG] 21 WLM Italia 0x000000010b6f5355 main + 1173\r\n[DEBUG] 22 libdyld.dylib 0x00000001162b7bbd start + 1\r\n[DEBUG] 23 ??? 0x0000000000000001 0x0 + 1\r\n[DEBUG] )\r\n{code}\r\n", "attachment": [ { "id": "67954", "filename": "crashlog.crash", "author": { "name": "ferdi.traversa", "key": "ferdi.traversa", "displayName": "Ferdinando Traversa", "active": true, "timeZone": "Europe/Rome" }, "created": "2021-07-20T13:01:10.000+0000", "size": 101172, "mimeType": "application/octet-stream" } ], "flagged": false, "summary": "Opening again a webdialog after you've opened and closed it causes a crash on iOS", "creator": { "name": "ferdi.traversa", "key": "ferdi.traversa", "displayName": "Ferdinando Traversa", "active": true, "timeZone": "Europe/Rome" }, "subtasks": [], "reporter": { "name": "ferdi.traversa", "key": "ferdi.traversa", "displayName": "Ferdinando Traversa", "active": true, "timeZone": "Europe/Rome" }, "environment": "Appcelerator Titanium 10.0.0.GA with ti.webdialog 3.0.0 and iOS 14.7", "comment": { "comments": [ { "id": "458875", "author": { "name": "ferdi.traversa", "key": "ferdi.traversa", "displayName": "Ferdinando Traversa", "active": true, "timeZone": "Europe/Rome" }, "body": "Workaround: use \r\n{code} \r\nif (OS_ANDROID || !Dialog.isOpen()) {\r\n// Dialog opening code\r\n}\r\n{code}\r\n\r\nIt seems that the window doesn't close instantly even if it seems closed, so it raises a crash when reopened instantly.", "updateAuthor": { "name": "ferdi.traversa", "key": "ferdi.traversa", "displayName": "Ferdinando Traversa", "active": true, "timeZone": "Europe/Rome" }, "created": "2021-07-20T13:23:36.000+0000", "updated": "2021-07-20T13:39:03.000+0000" }, { "id": "458876", "author": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "body": "[~ferdi.traversa] I don't believe this is caused by the WebDialog module, the code below works ok for opening and closing a WebDialog multiple times\r\n\r\n{code:js}\r\nconst wd = require('ti.webdialog');\r\nconst win = Ti.UI.createWindow();\r\nwd.addEventListener('close', () => {\r\n\tconsole.log('webdialog closed');\r\n});\r\nwin.addEventListener('click', () => {\r\n\tif (!wd.isSupported()) {\r\n\t\tconsole.log('not supported');\r\n\t\treturn;\r\n\t}\r\n\twd.open({\r\n\t\turl: 'https://axway.com',\r\n\t\tdismissButtonStyle: wd.DISMISS_BUTTON_STYLE_DONE\r\n\t});\r\n});\r\nwin.open();\r\n{code}\r\n\r\nI believe what is happening here is that every time you are calling the {{retrieveUserData}} function it is adding a new event listener to {{start_login}} [here|https://github.com/ferdi2005/monumenti/blob/7175d446272e5fae259933df029f772258656da8/app/controllers/upload/config.js#L207-L209], so there are multiple calls to {{startLogin}} that are attempting to open the WebDialog multiple times causing this error. That's why calling {{Dialog.isOpen()}} is fixing this. I've tried to reduce down your code to demonstrate this\r\n\r\n{code:js}const wd = require('ti.webdialog');\r\nlet loggedIn = false;\r\n\r\nconst win = Ti.UI.createWindow();\r\nconst loginBtn = Ti.UI.createButton({ title: 'Click me login', top: 100 });\r\nconst logoutBtn = Ti.UI.createButton({ title: 'Click me to logout', top: 150 });\r\nlogoutBtn.addEventListener('click', () => {\r\n\tloggedIn = false;\r\n\tsetupLoginFlow();\r\n});\r\n\r\nfunction userLogin() {\r\n\tconsole.log('userLogin called');\r\n\tif (!wd.isSupported()) {\r\n\t\tconsole.log('not supported');\r\n\t\treturn;\r\n\t}\r\n\twd.open({\r\n\t\turl: 'https://axway.com',\r\n\t\tdismissButtonStyle: wd.DISMISS_BUTTON_STYLE_DONE\r\n\t});\r\n\twd.addEventListener('close', () => {\r\n\t\tconsole.log('webdialog closed');\r\n\t\tloggedIn = true;\r\n\t\tsetupLoginFlow();\r\n\t});\r\n}\r\n\r\nfunction setupLoginFlow() {\r\n\tif (loggedIn) {\r\n\t\tloginBtn.hide();\r\n\t} else {\r\n\t\tloginBtn.show();\r\n\t\tloginBtn.addEventListener('click', () => {\r\n\t\t\tuserLogin();\r\n\t\t})\r\n\t}\r\n}\r\n\r\n\r\nwin.add(loginBtn);\r\nwin.add(logoutBtn);\r\nwin.open();\r\nsetupLoginFlow();\r\n{code}\r\n\r\nWhat I would recommend is making your event handler a named function and then removing it after calling userLogin, as you always appear to be calling {{retrieveUserData}} that should ensure you only have one event handler on the button at a time.\r\n\r\n{code:js}\r\nconst wd = require('ti.webdialog');\r\nlet loggedIn = false;\r\n\r\nconst win = Ti.UI.createWindow();\r\nconst loginBtn = Ti.UI.createButton({ title: 'Click me login', top: 100 });\r\nconst logoutBtn = Ti.UI.createButton({ title: 'Click me to logout', top: 150 });\r\nlogoutBtn.addEventListener('click', () => {\r\n\tloggedIn = false;\r\n\tsetupLoginFlow();\r\n});\r\n\r\nfunction userLogin() {\r\n\tconsole.log('userLogin called');\r\n\tif (!wd.isSupported()) {\r\n\t\tconsole.log('not supported');\r\n\t\treturn;\r\n\t}\r\n\twd.open({\r\n\t\turl: 'https://axway.com',\r\n\t\tdismissButtonStyle: wd.DISMISS_BUTTON_STYLE_DONE\r\n\t});\r\n\twd.addEventListener('close', () => {\r\n\t\tconsole.log('webdialog closed');\r\n\t\tloggedIn = true;\r\n\t\tsetupLoginFlow();\r\n\t});\r\n}\r\n\r\nfunction setupLoginFlow() {\r\n\tif (loggedIn) {\r\n\t\tloginBtn.hide();\r\n\t} else {\r\n\t\tloginBtn.show();\r\n\t\tloginBtn.addEventListener('click', function login () { // EDIT: changed to named function\r\n\t\t\tuserLogin();\r\n\t\t\tloginBtn.removeEventListener('click', login); // EDIT: removing event listener now\r\n\t\t});\r\n\t}\r\n}\r\nwin.add(loginBtn);\r\nwin.add(logoutBtn);\r\nwin.open();\r\nsetupLoginFlow();\r\n{code}", "updateAuthor": { "name": "eharris", "key": "eharris", "displayName": "Ewan Harris", "active": true, "timeZone": "Europe/Dublin" }, "created": "2021-07-20T13:59:25.000+0000", "updated": "2021-07-20T13:59:25.000+0000" }, { "id": "458885", "author": { "name": "ferdi.traversa", "key": "ferdi.traversa", "displayName": "Ferdinando Traversa", "active": true, "timeZone": "Europe/Rome" }, "body": "Woops! Thank you very much Ewan for spotting the real issue.", "updateAuthor": { "name": "ferdi.traversa", "key": "ferdi.traversa", "displayName": "Ferdinando Traversa", "active": true, "timeZone": "Europe/Rome" }, "created": "2021-07-22T11:30:56.000+0000", "updated": "2021-07-22T11:30:56.000+0000" } ], "maxResults": 3, "total": 3, "startAt": 0 } } }