I have a faceless Mac OS X app which needs to copy selection from other apps. I achieve this by simulating CMD+C keystrokes. It works perfectly. But there is a, I think it's critical, side effect. It'll override users' pasteboard without their permission. So I was thinking before I copying selection I should save pasteboard content and then restore it. Can someone give me some hint, maybe sample code?
Asked
Active
Viewed 1,466 times
13
-
1You should look into the Accessibility API. It'll get you what you want without ugly hacks. – Joakim Braun Nov 01 '11 at 19:01
-
@JoakimBraun I wish the Accessibility API could cover all the cases. – Keith Smiley Jul 10 '13 at 20:03
3 Answers
9
Here's a category on NSPasteboard
that I wrote to do this. It seems to work pretty well.
@implementation NSPasteboard (SaveAndRestore)
// save current contents as an array of pasteboard items
- (NSArray *)save
{
NSMutableArray *archive=[NSMutableArray array];
for (NSPasteboardItem *item in [self pasteboardItems])
{
NSPasteboardItem *archivedItem=[[NSPasteboardItem alloc] init];
for (NSString *type in [item types])
{
/* The mutableCopy performs a deep copy of the data. This avoids
memory leak issues (bug in Cocoa?), which you might run into if
you don't copy the data. */
NSData *data=[[item dataForType:type] mutableCopy];
if (data) { // nil safety check
[archivedItem setData:data forType:type];
}
}
[archive addObject:archivedItem];
}
return archive;
}
// restore previously saved data
- (void)restore:(NSArray *)archive
{
[self clearContents];
[self writeObjects:archive];
}
@end

Nick Moore
- 15,547
- 6
- 61
- 83
-
great man, the second time in less then a hour you helped me out. But sadly it is not compatible with your other answer http://stackoverflow.com/a/4333926/207616 the paste process is simply to slow, so that the pasteboard is restored before paste (even if its called in code later) – Feb 20 '12 at 23:59
-
It should work reliably if you just increase the delay, to about 1 second. – Nick Moore Feb 21 '12 at 10:31
-
yep did that (even 0.01 works) but I don't like such hacky tricks. Its unclear what will happen if the pasteboard data volume exceed a certain level but anyway thanks for the response =) – Feb 21 '12 at 12:52
-
-
nope, haven't looked deeper because the App I was working on, didn't get developed since :D ( oh this is over 2 years old :-o ) – Mar 25 '14 at 20:14
2
Alternative self-contained implementation using object associations:
#import <objc/runtime.h>
static void * kArchiveKey = &kArchiveKey;
@implementation NSPasteboard (SaveRestore)
- (void)setArchive:(NSArray *)newArchive
{
objc_setAssociatedObject(self, kArchiveKey, newArchive, OBJC_ASSOCIATION_RETAIN);
}
- (NSArray *)archive
{
return objc_getAssociatedObject(self, kArchiveKey);
}
- (void)save
{
NSMutableArray *archive = [NSMutableArray array];
for (NSPasteboardItem *item in [self pasteboardItems]) {
NSPasteboardItem *archivedItem = [[NSPasteboardItem alloc] init];
for (NSString *type in [item types]) {
NSData *data = [item dataForType:type];
if (data) {
[archivedItem setData:data forType:type];
}
}
[archive addObject:archivedItem];
}
[self setArchive:archive];
}
- (void)restore
{
[self clearContents];
[self writeObjects:[self archive]];
}
@end

djromero
- 19,551
- 4
- 71
- 68
1
Look at NSPasteboard
.
+[NSPasteboard generalPasteboard]
will give you the shared pasteboard and you can use that class to get and set the contents.

Ken Aspeslagh
- 11,484
- 2
- 36
- 42