2

How can I programmatically copy formatted text (e.g. italic) from a UITextView, so that when pasted into another program (e.g. Mail) the formatting will be retained? I'm assuming the correct approach is to copy an NSAttributedString to the pasteboard. Right now, I am able to copy a regular string to the pasteboard via the following:

NSString *noteTitleAndBody = [NSString stringWithFormat:@"%@\n%@", [document title], [document body]];
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
pasteboard.string = noteTitleAndBody;

I noticed that if I select and copy text from my UITextView with the standard text selection Copy menu item, it works as desired. But I need to access this via a button I've created.

I thought perhaps I could just call the UIResponderStandardEditActions Copy method. Using the following, the paste into Mail did retain the formatting, but my app also crashed as a result.

NSMutableAttributedString *noteTitleAndBody = [[NSMutableAttributedString alloc] initWithString:[document title]];
[noteTitleAndBody appendAttributedString:[document body]];
[noteTitleAndBody copy:nil];

Examples of the correct way to do this would be greatly appreciated.

PS - I am aware that there are existing threads related to NSAttributedString and the pasteboard, but they seem to either be for Cocoa, don't reference the UIResponderStandardEditActions Copy method, or predate iOS 6 where many of the UITextView attributes became available.

Community
  • 1
  • 1
DenVog
  • 4,226
  • 3
  • 43
  • 72

1 Answers1

1

The following will work for whatever textView is currently first responder:

[UIApplication sharedApplication] sendAction:@selector(copy:) to:nil from:self forEvent:nil];

Since my copy button is only accessible when my textView had resigned firstResponder, I had to do a little more:

[self.noteTextView select:self];
self.noteTextView.selectedRange = NSMakeRange(0, [self.noteTextView.text length]);
[[UIApplication sharedApplication] sendAction:@selector(copy:) to:nil from:self forEvent:nil];
[self.noteTextView resignFirstResponder];

Thanks to the following posts which pointed me in the right direction:

Perform copy/cut from UIResponderStandardEditActions

can I call a select method from UIResponderStandardEditActions?

Community
  • 1
  • 1
DenVog
  • 4,226
  • 3
  • 43
  • 72
  • 1
    You don't have to make the `UITextView` become `firstResponder`, you can just call `sendAction:@selector(copy:) to: self.noteTextView` – Smilin Brian Oct 24 '12 at 23:42
  • Thanks for the suggestion. This works, as long as I continue to do the range selection for the view: self.noteTextView.selectedRange = NSMakeRange(0, [self.noteTextView.text length]); – DenVog Oct 25 '12 at 17:04