{ "id": "162720", "key": "TIMOB-23797", "fields": { "issuetype": { "id": "4", "description": "An improvement or enhancement to an existing feature or task.", "name": "Improvement", "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": "18253", "name": "Release 5.5.0", "archived": false, "released": true, "releaseDate": "2016-09-13" } ], "resolution": { "id": "1", "description": "A fix for this issue is checked into the tree and tested.", "name": "Fixed" }, "resolutiondate": "2016-08-30T21:47:10.000+0000", "created": "2016-08-22T05:18:41.000+0000", "priority": { "name": "High", "id": "2" }, "labels": [ "qe-5.5.0" ], "versions": [ { "id": "18253", "name": "Release 5.5.0", "archived": false, "released": true, "releaseDate": "2016-09-13" } ], "issuelinks": [ { "id": "52502", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "outwardIssue": { "id": "162729", "key": "TIMOB-23798", "fields": { "summary": "iOS: Ti.UI.Clipboard.clearData() crashes when no MIME type is provided", "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": "High", "id": "2" }, "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false } } } }, { "id": "52598", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "outwardIssue": { "id": "162958", "key": "TIMOB-23858", "fields": { "summary": "iOS: getItems() on cleared Pasteboard errors and crashes", "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": "High", "id": "2" }, "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false } } } }, { "id": "52595", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "outwardIssue": { "id": "162953", "key": "TIMOB-23857", "fields": { "summary": "iOS: Expose more Pasteboard Item's APIs", "status": { "description": "The issue is open and ready for the assignee to start work on it.", "name": "Open", "id": "1", "statusCategory": { "id": 2, "key": "new", "colorName": "blue-gray", "name": "To Do" } }, "priority": { "name": "Low", "id": "4" }, "issuetype": { "id": "4", "description": "An improvement or enhancement to an existing feature or task.", "name": "Improvement", "subtask": false } } } }, { "id": "52504", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "outwardIssue": { "id": "162730", "key": "TIMOB-23799", "fields": { "summary": "iOS: Support Named Pasteboards", "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": "Medium", "id": "3" }, "issuetype": { "id": "4", "description": "An improvement or enhancement to an existing feature or task.", "name": "Improvement", "subtask": false } } } }, { "id": "52499", "type": { "id": "10003", "name": "Relates", "inward": "relates to", "outward": "relates to" }, "inwardIssue": { "id": "161074", "key": "TIMOB-23519", "fields": { "summary": "iOS10: Expose new Ti.UI.Pasteboard APIs", "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": "High", "id": "2" }, "issuetype": { "id": "2", "description": "A new feature of the product, which has yet to be developed.", "name": "New Feature", "subtask": false } } } } ], "assignee": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "updated": "2016-09-06T21:58:04.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": "There are several features of Pasteboards described in https://developer.apple.com/reference/uikit/uipasteboard that we currently do not support: Named pasteboards (TIMOB-23799), localOnly, expiration time/date, etc.\r\n\r\nIdeally, we would support these features (and avoid the deprecations introduced with iOS 10).", "attachment": [], "flagged": false, "summary": "iOS: Improve Pasteboard support", "creator": { "name": "ewieber", "key": "ewieber", "displayName": "Eric Wieber", "active": false, "timeZone": "America/Los_Angeles" }, "subtasks": [], "reporter": { "name": "ewieber", "key": "ewieber", "displayName": "Eric Wieber", "active": false, "timeZone": "America/Los_Angeles" }, "environment": null, "closedSprints": [ { "id": 704, "state": "closed", "name": "2016 Sprint 18 SDK", "startDate": "2016-08-27T00:18:36.960Z", "endDate": "2016-09-10T00:18:00.000Z", "completeDate": "2016-09-09T20:26:13.865Z", "originBoardId": 114 } ], "comment": { "comments": [ { "id": "393758", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "Good one. Named pasteboards are a big thing and need further investigation to be integrated in the existing API's, so I would like to get that in a new ticket like \"iOS: Support named pasteboards\". For the new {{setItems}} method that also takes {{UIPasteboardOption}} options, I just implemented the new API (for 6.1.0). PR coming shortly.", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-08-22T07:38:53.000+0000", "updated": "2016-08-22T07:38:53.000+0000" }, { "id": "393760", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "PR (master): https://github.com/appcelerator/titanium_mobile/pull/8247\r\nPR (5_5_X): https://github.com/appcelerator/titanium_mobile/pull/8290\r\nPR (6_0_X): https://github.com/appcelerator/titanium_mobile/pull/8289\r\n\r\nDemo:\r\n{code:javascript}\r\nvar win = Ti.UI.createWindow({\r\n backgroundColor : \"#fff\"\r\n}); \r\n\r\nvar btn1 = Ti.UI.createButton({\r\n title : \"Set clipboard items\",\r\n top: 40\r\n});\r\n\r\nvar btn2 = Ti.UI.createButton({\r\n title : \"Get clipboard items\",\r\n top: 80\r\n});\r\n \r\nbtn1.addEventListener(\"click\", function() {\r\n\tvar localOnly = Ti.UI.CLIPBOARD_OPTION_LOCAL_ONLY;\r\n\tvar expirationDate = Ti.UI.CLIPBOARD_OPTION_EXPIRATION_DATE;\r\n\t\r\n Ti.UI.Clipboard.setItems({\r\n\t items: [{\r\n\t \"text/plain\": \"John\",\r\n\t },{\r\n\t \"text/plain\": \"Doe\"\r\n\t }],\r\n\t options: {\r\n\t localOnly: true,\r\n\t expirationDate: new Date(2020, 04, 20)\r\n\t }\r\n\t});\r\n});\r\n\r\nbtn2.addEventListener(\"click\", function() {\r\n alert(Ti.UI.Clipboard.getItems());\r\n});\r\n \r\nwin.add(btn1);\r\nwin.add(btn2);\r\nwin.open();\r\n{code}", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-08-22T08:05:11.000+0000", "updated": "2016-08-30T21:18:29.000+0000" }, { "id": "393810", "author": { "name": "ewieber", "key": "ewieber", "displayName": "Eric Wieber", "active": false, "timeZone": "America/Los_Angeles" }, "body": "[~hansknoechel], sounds good. Created TIMOB-23799 for Named Pasteboard support.", "updateAuthor": { "name": "ewieber", "key": "ewieber", "displayName": "Eric Wieber", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2016-08-22T18:00:29.000+0000", "updated": "2016-08-22T18:00:29.000+0000" }, { "id": "395089", "author": { "name": "ewieber", "key": "ewieber", "displayName": "Eric Wieber", "active": false, "timeZone": "America/Los_Angeles" }, "body": "The {{getItems()}} method is throwing an error when there are no items in the Pasteboard:\r\n{code}\r\n[ERROR] : 2016-09-01 06:35:19.000 PasteboardCheck[12358:22821338] -[_NSZeroData boundBridge:withKrollObject:]: unrecognized selector sent to instance 0x79e63d80\r\n[ERROR] : Script Error {\r\n[ERROR] : column = 39;\r\n[ERROR] : line = 58;\r\n[ERROR] : message = \"-[_NSZeroData boundBridge:withKrollObject:]: unrecognized selector sent to instance 0x79e63d80\";\r\n[ERROR] : stack = \"[native code]\\n\";\r\n[ERROR] : }\r\n{code}\r\n\r\n*Steps to reproduce issue*\r\n1. Create a new project\r\n2. Add the below lines to the code, preferably on a button press:\r\n{{Ti.UI.Clipboard.clearData();}}\r\n{{alert(Ti.UI.Clipboard.getItems());}}\r\n3. Run the project and press the button or call the methods\r\n\r\n*Expected results*\r\n{{getItems()}} returns an empty array, without error\r\n\r\n*Actual results*\r\nThe above error is thrown\r\n\r\n*Notes*\r\nThis is stated in the docs for {{setItems()}}, but is there a way we can handle it better? Perhaps checking {{numberOfItems}} and using that to make sure the Pasteboard is not empty first?\r\nAlthough a runtime error is thrown, you can see an empty array returned from {{getItems()}} if you dismiss the error and call it again. However, If you clear the data with {{clearData()}} and then call {{getItems()}} too many times (sometimes 2), then the app will crash with the below error:\r\n{code}\r\n[ERROR] : The application has crashed with an uncaught exception 'NSInvalidArgumentException'.\r\n[ERROR] : Reason:\r\n[ERROR] : -[_NSZeroData unboundBridge:]: unrecognized selector sent to instance 0x79191700\r\n[ERROR] : Stack trace:\r\n[ERROR] : \r\n[ERROR] : 0 CoreFoundation 0x06f851f0 __exceptionPreprocess + 160\r\n[ERROR] : 1 libobjc.A.dylib 0x065fae66 objc_exception_throw + 52\r\n[ERROR] : 2 CoreFoundation 0x06ffe3dc -[NSObject(NSObject) doesNotRecognizeSelector:] + 172\r\n[ERROR] : 3 CoreFoundation 0x06f0434c ___forwarding___ + 1052\r\n[ERROR] : 4 CoreFoundation 0x06f03f0e _CF_forwarding_prep_0 + 14\r\n[ERROR] : 5 PasteboardCheck 0x00061d6e -[KrollBridge unregisterProxy:] + 158\r\n[ERROR] : 6 PasteboardCheck 0x00070839 KrollFinalizer + 489\r\n[ERROR] : 7 PasteboardCheck 0x0042c42c _ZN2TI20JSCallbackObjectData8finalizeENS_6HandleINS_7UnknownEEEPv + 108\r\n[ERROR] : 8 PasteboardCheck 0x005fb4ae _ZN2TI9WeakBlock5sweepEv + 110\r\n[ERROR] : 9 PasteboardCheck 0x005fd358 _ZN2TI7WeakSet5sweepEv + 40\r\n[ERROR] : 10 PasteboardCheck 0x004eedbc _ZN2TI11MarkedBlock5sweepENS0_9SweepModeE + 28\r\n[ERROR] : 11 PasteboardCheck 0x003c08fa _ZN2TI18IncrementalSweeper7doSweepEd + 154\r\n[ERROR] : 12 PasteboardCheck 0x003c084b _ZN2TI18IncrementalSweeper6doWorkEv + 27\r\n[ERROR] : 13 PasteboardCheck 0x003bf566 _ZN2TI9HeapTimer12timerDidFireEP16__CFRunLoopTimerPv + 166\r\n[ERROR] : 14 CoreFoundation 0x06f115d6 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22\r\n[ERROR] : 15 CoreFoundation 0x06f110ed __CFRunLoopDoTimer + 1213\r\n[ERROR] : 16 CoreFoundation 0x06f10bff __CFRunLoopDoTimers + 255\r\n[ERROR] : 17 CoreFoundation 0x06f086c0 __CFRunLoopRun + 2208\r\n[ERROR] : 18 CoreFoundation 0x06f07bab CFRunLoopRunSpecific + 395\r\n[ERROR] : 19 CoreFoundation 0x06f07a0b CFRunLoopRunInMode + 123\r\n[ERROR] : 20 GraphicsServices 0x08241b4c GSEventRunModal + 177\r\n[ERROR] : 21 GraphicsServices 0x082419c7 GSEventRun + 80\r\n[ERROR] : 22 UIKit 0x025480eb UIApplicationMain + 148\r\n[ERROR] : 23 PasteboardCheck 0x000462e8 main + 408\r\n[ERROR] : 24 libdyld.dylib 0x07d96799 start + 1\r\n[ERROR] : 25 ??? 0x00000001 0x0 + 1\r\n[ERROR] : \r\n[ERROR] : 2016-09-01 06:37:27.651 PasteboardCheck[12715:22825481] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_NSZeroData unboundBridge:]: unrecognized selector sent to instance 0x79191700'\r\n[ERROR] : *** First throw call stack:\r\n[ERROR] : (\r\n[ERROR] : \t0 CoreFoundation 0x06f85212 __exceptionPreprocess + 194\r\n[ERROR] : \t1 libobjc.A.dylib 0x065fae66 objc_exception_throw + 52\r\n[ERROR] : \t2 CoreFoundation 0x06ffe3dc -[NSObject(NSObject) doesNotRecognizeSelector:] + 172\r\n[ERROR] : \t3 CoreFoundation 0x06f0434c ___forwarding___ + 1052\r\n[ERROR] : \t4 CoreFoundation 0x06f03f0e _CF_forwarding_prep_0 + 14\r\n[ERROR] : \t5 PasteboardCheck 0x00061d6e -[KrollBridge unregisterProxy:] + 158\r\n[ERROR] : \t6 PasteboardCheck 0x00070839 KrollFinalizer + 489\r\n[ERROR] : \t7 PasteboardCheck 0x0042c42c _ZN2TI20JSCallbackObjectData8finalizeENS_6HandleINS_7UnknownEEEPv + 108\r\n[ERROR] : \t8 PasteboardCheck 0x005fb4ae _ZN2TI9WeakBlock5sweepEv + 110\r\n[ERROR] : \t9 PasteboardCheck 0x005fd358 _ZN2TI7WeakSet5sweepEv + 40\r\n[ERROR] : \t10 PasteboardCheck 0x004eedbc _ZN2TI11MarkedBlock5sweepENS0_9SweepModeE + 28\r\n[ERROR] : \t11 PasteboardCheck 0x003c08fa _ZN2TI18IncrementalSweeper7doSweepEd + 154\r\n[ERROR] : \t12 PasteboardCheck 0x003c084b _ZN2TI18IncrementalSweeper6doWorkEv + 27\r\n[ERROR] : \t13 PasteboardCheck 0x003bf566 _ZN2TI9HeapTimer12timerDidFireEP16__CFRunLoopTimerPv + 166\r\n[ERROR] : \t14 CoreFoundation 0x06f115d6 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 22\r\n[ERROR] : \t15 CoreFoundation 0x06f110ed __CFRunLoopDoTimer + 1213\r\n[ERROR] : \t16 CoreFoundation 0x06f10bff __CFRunLoopDoTimers + 255\r\n[ERROR] : \t17 CoreFoundation 0x06f086c0 __CFRunLoopRun + 2208\r\n[ERROR] : \t18 CoreFoundation 0x06f07bab CFRunLoopRunSpecific + 395\r\n[ERROR] : \t19 CoreFoundation 0x06f07a0b CFRunLoopRunInMode + 123\r\n[ERROR] : \t20 GraphicsServices 0x08241b4c GSEventRunModal + 177\r\n[ERROR] : \t21 GraphicsServices 0x082419c7 GSEventRun + 80\r\n[ERROR] : \t22 UIKit 0x025480eb UIApplicationMain + 148\r\n[ERROR] : \t23 PasteboardCheck 0x000462e8 main + 408\r\n[ERROR] : \t24 libdyld.dylib 0x07d96799 start + 1\r\n[ERROR] : \t25 ??? 0x00000001 0x0 + 1\r\n[ERROR] : )\r\n[ERROR] : libc++abi.dylib: terminating with uncaught exception of type NSException\r\n[TRACE] : [PasteboardCheck] -[_NSZeroData unboundBridge:]: unrecognized selector sent to instance 0x79191700\r\n[TRACE] : [PasteboardCheck] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_NSZeroData unboundBridge:]: unrecognized selector sent to instance 0x79191700'\r\n{code}", "updateAuthor": { "name": "ewieber", "key": "ewieber", "displayName": "Eric Wieber", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2016-09-01T13:51:04.000+0000", "updated": "2016-09-01T16:06:49.000+0000" }, { "id": "395094", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "[~ewieber] As far as I understood, the iOS 10 method {{setItems}} persists the item at a different internal location to enable options like the expire- and localOnly configuration. So using {{clearData}} will only clear the items that have been set with the known methods:\r\n\r\n{quote}\r\nStarting in iOS 10 there is a new Handoff feature which allows the general pasteboard contents to automatically transfer between devices. You can control Handoff behavior for pasteboard contents, and can set a pasteboard to expire, by using the {{setItems(_:options:\\)}} method, as follows:\r\n\r\nTo exclude a pasteboard from Handoff, call the {{setItems(_:options:\\)}} method with the localOnly option.\r\n\r\nTo indicate an expiration time and date for copied data, call the {{setItems(_:options:\\)}} method with the expirationDate option. At the time and date that you set, the system removes the pasteboard items from the pasteboard.\r\n{quote}\r\n\r\nSo {{setItems}} is primary for enabling handoff with those items and {{clearData}} is specific to the system-wide pasteboard. See the [official docs|https://developer.apple.com/reference/uikit/uipasteboard].", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-09-01T14:04:23.000+0000", "updated": "2016-09-01T14:17:12.000+0000" }, { "id": "395104", "author": { "name": "ewieber", "key": "ewieber", "displayName": "Eric Wieber", "active": false, "timeZone": "America/Los_Angeles" }, "body": "I see, but there is either some connection between the two or there is an issue with calling {{getItems}} on an empty Pasteboard, hence the crash. What are your thoughts on using {{numberOfItems}} to make sure that the Pasteboard has >0 items before calling {{\\[\\[\\[UIPasteboard generalPasteboard\\] items\\] retain\\]}}? ", "updateAuthor": { "name": "ewieber", "key": "ewieber", "displayName": "Eric Wieber", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2016-09-01T16:12:28.000+0000", "updated": "2016-09-01T16:14:25.000+0000" }, { "id": "395105", "author": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "body": "Well, the number of items is > 0, but those items are invalid from previous {{setItems}} calls that had an invalid mime-type specified. The whole ticket should have gone into 6.1.0. But for now, I would suggest an improvement-ticket to summarize your finding that can go into 6.0.0, so I have more time to investigate the different use-cases you want.", "updateAuthor": { "name": "hknoechel", "key": "hansknoechel", "displayName": "Hans Knöchel", "active": true, "timeZone": "Europe/Berlin" }, "created": "2016-09-01T16:15:27.000+0000", "updated": "2016-09-01T16:15:27.000+0000" }, { "id": "395147", "author": { "name": "ewieber", "key": "ewieber", "displayName": "Eric Wieber", "active": false, "timeZone": "America/Los_Angeles" }, "body": "TIMOB-23858 created to continue the discussion/investigation on the {{clearData}} and {{getItems}} issue", "updateAuthor": { "name": "ewieber", "key": "ewieber", "displayName": "Eric Wieber", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2016-09-01T21:38:37.000+0000", "updated": "2016-09-01T21:38:37.000+0000" }, { "id": "395444", "author": { "name": "ewieber", "key": "ewieber", "displayName": "Eric Wieber", "active": false, "timeZone": "America/Los_Angeles" }, "body": "Since TIMOB-23799, TIMOB-23857, and TIMOB-23858 cover the issue above and the implementation of other APIs, this can be considered done.\r\nTested using:\r\nMacOS 10.12 (16A239m)\r\nStudio 4.7.1.201608190732\r\nTi SDK 5.5.0.v20160904203801\r\nAppc NPM 4.2.7\r\nAppc CLI 5.5.0-5\r\nAlloy 1.9.1\r\nXcode 8.0 (8S201h)\r\n\r\nI am now able to get and set items on Pasteboards, using the {{localOnly}} and expiration date properties, without error. Tested using the provided samples as well as my own test apps that get/set multiple items on a Pasteboard and use one or both of the localOnly and expiration date properties.", "updateAuthor": { "name": "ewieber", "key": "ewieber", "displayName": "Eric Wieber", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2016-09-06T21:58:04.000+0000", "updated": "2016-09-06T21:58:04.000+0000" } ], "maxResults": 10, "total": 10, "startAt": 0 } } }