macOS - NSPasteboard not functioning as it used to??

Using 10.15.7 and Xcode 12.0

I've had an app for years which reads data off of the general pasteboard. This app is no longer behaving as it once did...
Code Block
// a standard service entry point- (void) xyzService:(NSPasteboard *)pboard userData:(NSString *)userData error:(NSString **)error; {    NSData *rtfData=[pboard dataForType:NSPasteboardTypeRTF];    if (rtfData!=nil) {... }...}


This used to reliably report the rtf data on the current pasteboard.

Now rtfData is a 0 byte non null Data object.

Has there been some change that I am just completely unaware of? Why would this just stop working?

NOTE: NSPasteboardTypeString still returns the usual response....

Thank-You for any help here!

Replies

Apologies for the formatting above.... Didn't see this until just now...
In any case should be:
Code Block l
// this is a standard service entry point
- (void) xyzService:(NSPasteboard *)pboard userData:(NSString *)userData error:(NSString **)error; {
...
NSData *rtfData=[pboard dataForType:NSPasteboardTypeRTF];   
if (rtfData!=nil) {
...
}
...
}


Have you tried examining the pasteboard state using Clipboard Viewer from the Xcode Additional Tools?
TyngJJ

ClipboardViewer does not provide an option for viewing the NSPasteboard that is presented to a Service using the above entry point... So it is not helpful in this circumstance.

With further research what I currently see is this:

On macOS a user can make a text selection in a given application and then use 1 of four 'direct' means of invoking a second application to act on that text selection. (I use 'direct' here to mean that the selection is not saved to the file system in some fashion and then this file is acted on by the second application)

The 4 mechanisms are:
drag the text to a window managed by the second application
drag the text to the dock icon of the second application
invoke a 'Service' by using one of the various menus which are available for 'Services' (the service is provided by second application)
invoke a keyboard shortcut associated with the second application

It used to be that these means would all yield the same RTFData.
This is no longer true.
The 2 drag mechanisms still yield the expected RTFData
The 'Service' and keyboard shortcut do NOT yield an RTFData (they do yield an NSPasteboardTypeString product)
Please note that the keyboard shortcut is a user interface convenience which in fact utilizes the 'Service'...

The upshot here is that what has changed is the 'pboard' in the standard service entry point:
Code Block
- (void) xyzService:(NSPasteboard *)pboard userData:(NSString *)userData error:(NSString **)error; {


This NSPasteboard no longer behaves as it did in the past!
Can someone please point me to where this change in functionality is documented!

Thanks!


I just tried an old app I have that reads rich text from files via the Services menu. It works fine. Maybe setup a virtual machine and test it there.
Etresoft;

Try recompiling that old app using Xcode 12 on macOS 10.15 and run again.

Using an old binary doesn't get to the issue.

Try recompiling that old app using Xcode 12 on macOS 10.15 and run again.

Using an old binary doesn't get to the issue.

I don't have 10.15 available just right now. But I built it on Xcode 12.2 and tested on Big Sur and it works fine. I tested that build in a 10.15.7 VM and it worked fine there too.

Those two cases where you are having problems are when the OS launches your app. It uses the bundle ID to find the app. So, if you are testing this on your development machine, there is no way to tell which executable it might run. If you have some old, buggy version that doesn't read RTF properly, it could be camped out on that version. You might be able to circumvent that by manually launching the app first and then trying the service. But the idea test for anything that integrates with OS services is a fresh install of the OS in a VM.
I'm interested to know why you haven't mentioned the NSServices definition in the app's Info.plist. Does it include the NSSendTypes you're looking for? Or was your app relying on an implementation detail that the pasteboard used to provide all available types to a service, rather than narrowing them by the accepted ones.
Hey TyngJJ & Etresoft!

Thank-you both for your help and thoughts here!! I REALLY appreciate it!

So the NSService 3 SendTypes are: 'com.apple.flat-rtfd', 'public-rtf', and 'public.plain-text'
These have not changed over the course of time but the service entry point results have changed.

So I took the app to Big Sur to compare with Etresoft's findings.
At this point it seems to be application related... Safari is NOT providing rtf in the service on either Calatina or Big Sur.

Here's some Big Sur logging from the service entry point shown earlier when the text selection is RTF
First you see Text Edit then Safari....

So, Etresoft if you are still listening and inclined please test with using Safari as the source application which is providing an rtf text selection....

Code Block
* TEXTEDIT *
2020-10-09 13:27:56.621448-0700  - BID:com.apple.TextEdit
2020-10-09 13:27:56.621599-0700  - pboard:(
    "public.utf8-plain-text",
    NSStringPboardType,
    "public.rtf",
    "NeXT Rich Text Format v1.0 pasteboard type",
    "public.utf16-external-plain-text",
    "CorePasteboardFlavorType 0x75743136"
)
2020-10-09 13:27:56.621651-0700  - pboard RTFD:(null)
2020-10-09 13:27:56.622996-0700  - pboard RTF:{length = 2131, bytes = 0x7b5c7274 66315c61 6e73695c 616e7369 ... 49207365 6e64207d }
2020-10-09 13:27:56.623128-0700  - pboard public.rtf:{length = 2131, bytes = 0x7b5c7274 66315c61 6e73695c 616e7369 ... 49207365 6e64207d }
2020-10-09 13:27:56.623595-0700  - pboard String:{length = 716, bytes = 0x0909596f 75206e65 65642074 6f206564 ... 20492073 656e6420 }
2020-10-09 13:27:56.623717-0700  - [pboard pasteboardItems]:(
    "<NSPasteboardItem: 0x600000eb64c0>"
)
2020-10-09 13:27:56.623800-0700  - pasteboardItem[0]:(
    "public.utf8-plain-text",
    "public.rtf",
    "public.utf16-external-plain-text"
)
2020-10-09 13:27:56.623901-0700  - pI RTFD:(null)
2020-10-09 13:27:56.624014-0700  - pI RTF:{length = 2131, bytes = 0x7b5c7274 66315c61 6e73695c 616e7369 ... 49207365 6e64207d }
2020-10-09 13:27:56.624094-0700  - pI public.rtf:{length = 2131, bytes = 0x7b5c7274 66315c61 6e73695c 616e7369 ... 49207365 6e64207d }
2020-10-09 13:27:56.624189-0700  - pI String:{length = 716, bytes = 0x0909596f 75206e65 65642074 6f206564 ... 20492073 656e6420 }
2020-10-09 13:27:56.624979-0700  - sender:com.apple.TextEdit NSPasteboardTypeRTF:2131
* SAFARI *
2020-10-09 13:28:15.270898-0700  - BID:com.apple.Safari
2020-10-09 13:28:15.271097-0700  - pboard:(
    "public.rtf",
    "NeXT Rich Text Format v1.0 pasteboard type",
    "public.utf8-plain-text",
    NSStringPboardType,
    "com.apple.flat-rtfd",
    "NeXT RTFD pasteboard type",
    "public.utf16-external-plain-text",
    "CorePasteboardFlavorType 0x75743136"
)
2020-10-09 13:28:15.272557-0700  - pboard RTFD:{length = 0, bytes = 0x}
2020-10-09 13:28:15.273071-0700  - pboard RTF:{length = 0, bytes = 0x}
2020-10-09 13:28:15.273242-0700  - pboard public.rtf:{length = 0, bytes = 0x}
2020-10-09 13:28:15.273731-0700  - pboard String:{length = 621, bytes = 0x310a596f 75206e65 65642074 6f206564 ... 652c2074 68656e20 }
2020-10-09 13:28:15.273921-0700  - [pboard pasteboardItems]:(
    "<NSPasteboardItem: 0x600000e10a80>"
)
2020-10-09 13:28:15.274031-0700  - pasteboardItem[0]:(
    "public.rtf",
    "public.utf8-plain-text",
    "com.apple.flat-rtfd",
    "public.utf16-external-plain-text"
)
2020-10-09 13:28:15.274170-0700  - pI RTFD:{length = 0, bytes = 0x}
2020-10-09 13:28:15.285873-0700  - pI RTF:{length = 0, bytes = 0x}
2020-10-09 13:28:15.286083-0700  - pI public.rtf:{length = 0, bytes = 0x}
2020-10-09 13:28:15.286269-0700  - pI String:{length = 621, bytes = 0x310a596f 75206e65 65642074 6f206564 ... 652c2074 68656e20 }


So, Etresoft if you are still listening and inclined please test with using Safari as the source application which is providing an rtf text selection....

I was only testing the functionality of NSPasteboard itself. In a service context, my app just reads from a selected path in the Finder. I thought that the system integration could explain the problem.

If this is really a Safari problem, then my suggestion would be to add HTML to your data types. RTF is pretty ubiquitous on macOS, but isn't the future. There is no guarantee that new code is going to support RTF like it has in the past. It does still say "NeXT", after all.

I do happen to have another service that extract links for pasting into Apple Support Communities. When I select a link (which is rich text) in Safari and use this service, I get an error. It seems like Safari is advertising this data, but not providing it. I tried changing this service to accept either "web content" or "URLs" but Safari won't provide any data. I think it is a Safari bug.

When I try the same operation in Google Chrome, my service isn't even listed. I guess Chrome isn't advertising this data. That's one way to handle it.

I'll go ahead and file a bug report on it. If you do too, that will be two.
Etresoft;

Thanks for contributing to this discussion and filing a bug report.
You said:
"...If this is really a Safari problem, then my suggestion would be to add HTML to your data types. RTF is pretty ubiquitous on macOS, but isn't the future. There is no guarantee that new code is going to support RTF like it has in the past. It does still say "NeXT", after all...."

So the answer is provided in my earlier log. Safari does NOT provide html to a service! For extra credit I DID enhance my app to acquire html data but unsurprisingly it is null. If you look at the log you will see that the "pboard.dataTypes" reported in the service entry point are:
Code Block
"public.rtf",
    "NeXT Rich Text Format v1.0 pasteboard type",
    "public.utf8-plain-text",
    NSStringPboardType,
    "com.apple.flat-rtfd",
    "NeXT RTFD pasteboard type",
    "public.utf16-external-plain-text",
    "CorePasteboardFlavorType 0x75743136"


So there is clearly a bug here. Safari reports "public.rtf" but does not provide that data to the service!

You said: 
"...If this is really a Safari problem, then my suggestion would be to add HTML to your data types. RTF is pretty ubiquitous on macOS, but isn't the future. There is no guarantee that new code is going to support RTF like it has in the past. It does still say "NeXT", after all...."

Sorry for the confusion. That was my initial reply. But then I realized that I had that old Automator service where I could test the exact same thing that you are seeing.

So there is clearly a bug here. Safari reports "public.rtf" but does not provide that data to the service!

I agree. To be clear, this bug will never be fixed in Catalina. You have one, maybe two weeks to file a bug report in Big Sur. There is a slight possibility that an updated Safari may contain the fix and may be released on Catalina. In the future, do not wait until the final days of an operating system to test for these kinds of bugs. This is what betas are for.