Copy NSAttributedString in UIPasteBoard

swift copy to clipboard
ios copy text to clipboard programmatically

How do you copy an NSAttributedString in the pasteboard, to allow the user to paste, or to paste programmatically (with - (void)paste:(id)sender, from UIResponderStandardEditActions protocol).

I tried:

UIPasteboard *pasteBoard = [UIPasteboard generalPasteboard];
[pasteBoard setValue:attributedString forPasteboardType:(NSString *)kUTTypeRTF];

but this crash with:

-[UIPasteboard setValue:forPasteboardType:]: value is not a valid property list type'

which is to be expected, because NSAttributedString is not a property list value.

If the user paste the content of the pasteboard in my app, I would like to keep all the standards and custom attributes of the attributed string.

I have found that when I (as a user of the application) copy rich text from a UITextView into the pasteboard, the pasteboard contains two types:

"public.text",
"Apple Web Archive pasteboard type

Based on that, I created a convenient category on UIPasteboard. (With heavy use of code from this answer).

It works, but: The conversion to html format means I will lose custom attributes. Any clean solution will be gladly accepted.

File UIPasteboard+AttributedString.h:

@interface UIPasteboard (AttributedString)

- (void) setAttributedString:(NSAttributedString *)attributedString;

@end

File UIPasteboard+AttributedString.m:

#import <MobileCoreServices/UTCoreTypes.h>

#import "UIPasteboard+AttributedString.h"

@implementation UIPasteboard (AttributedString)

- (void) setAttributedString:(NSAttributedString *)attributedString {
    NSString *htmlString = [attributedString htmlString]; // This uses DTCoreText category NSAttributedString+HTML - https://github.com/Cocoanetics/DTCoreText
    NSDictionary *resourceDictionary = @{ @"WebResourceData" : [htmlString dataUsingEncoding:NSUTF8StringEncoding],
    @"WebResourceFrameName":  @"",
    @"WebResourceMIMEType" : @"text/html",
    @"WebResourceTextEncodingName" : @"UTF-8",
    @"WebResourceURL" : @"about:blank" };



    NSDictionary *htmlItem = @{ (NSString *)kUTTypeText : [attributedString string],
        @"Apple Web Archive pasteboard type" : @{ @"WebMainResource" : resourceDictionary } };

    [self setItems:@[ htmlItem ]];
}


@end

Only implemented setter. If you want to write the getter, and/or put it on GitHub, be my guest :)

ios Copy NSAttributedString in UIPasteBoard?, How do you copy an NSAttributedString in the pasteboard, to allow the user to paste, or to paste programmatically (with - (void)paste:(id)sender, from  ¿Cómo se copia un NSAttributedString en la mesa de trabajo, para permitir que el usuario pegue o pegue programáticamente (con - (void)paste:(id)sender, desde el protocolo UIResponderStandardEditActions).

@Guillaume's approach using HTML doesn't work for me (at least in iOS 7.1 beta 5).

The cleaner solution is to insert NSAttributedStrings as RTF (plus plaintext fallback) into the paste board:

- (void)setAttributedString:(NSAttributedString *)attributedString {
    NSData *rtf = [attributedString dataFromRange:NSMakeRange(0, attributedString.length)
                               documentAttributes:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType}
                                            error:nil];
    self.items = @[@{(id)kUTTypeRTF: [[NSString alloc] initWithData:rtf encoding:NSUTF8StringEncoding],
                     (id)kUTTypeUTF8PlainText: attributedString.string}];
}

Swift 2.3

public extension UIPasteboard {
  public func set(attributedString: NSAttributedString?) {

    guard let attributedString = attributedString else {
      return
    }

    do {
      let rtf = try attributedString.dataFromRange(NSMakeRange(0, attributedString.length), documentAttributes: [NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType])
      items = [[kUTTypeRTF as String: NSString(data: rtf, encoding: NSUTF8StringEncoding)!, kUTTypeUTF8PlainText as String: attributedString.string]]

    } catch {

    }
  }
}

Swift 3

import MobileCoreServices
public extension UIPasteboard {
  public func set(attributedString: NSAttributedString?) {

    guard let attributedString = attributedString else {
      return
    }

    do {
      let rtf = try attributedString.data(from: NSMakeRange(0, attributedString.length), documentAttributes: [NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType])
      items = [[kUTTypeRTF as String: NSString(data: rtf, encoding: String.Encoding.utf8.rawValue)!, kUTTypeUTF8PlainText as String: attributedString.string]]

    } catch {

    }
  }
}

Copy attributed string to pasteboard · GitHub, I created a convenient category on UIPasteboard. (With heavy use of code from this answer). I have found that when I (as a user of the application) copy rich  Copying a string to the Clipboard using Objective-C is a simple two-line process. But what if you want to copy from an HTML source and maintain its color and formatting? Doing this requires creating an NSAttributedString from the HTML, then converting it into an NSData object, and then passing it to the UIPasteboard using a Rich Text (RTF) type.

It is quite simple:

  #import <MobileCoreServices/UTCoreTypes.h>

  NSMutableDictionary *item = [[NSMutableDictionary alloc] init];

  NSData *rtf = [attributedString dataFromRange:NSMakeRange(0, attributedString.length)
                             documentAttributes:@{NSDocumentTypeDocumentAttribute: NSRTFDTextDocumentType}
                                          error:nil];

  if (rtf) {
    [item setObject:rtf forKey:(id)kUTTypeFlatRTFD];
  }

  [item setObject:attributedString.string forKey:(id)kUTTypeUTF8PlainText];

  UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
  pasteboard.items = @[item];

🦔 ✊ 👊🏼 Copy NSAttributedString to UIPasteBoard, UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];. NSDictionary *​stringAttributes = @{. NSFontAttributeName: [UIFont  As of Snow Leopard, NSAttributedString (when powered up by AppKit) conforms to NSPasteboardWriting, so you can simply do this: [pb clearContents]; [pb writeObjects:arrayOfAttributedStrings]; You can send NSArray an arrayWithObject: message if you have only one attributed string you want to put on the pasteboard.

The pasteboard manager in OSX can auto convert between a lot of textual and image types.

For rich text types, you'd usually place RTF into the pasteboard. You can create RTF representation from an attributed string, and vice versa. See the "NSAttributedString Application Kit Additions Reference".

If you have images included as well, then use the RTFd instead of RTF flavor.

I don't know the MIME types for these (I'm used to the Carbon Pasteboard API, not the Cocoa one), but you can convert between UTIs, Pboard and MIME Types using the UTType API.

UTI for RTF is "public.rtf", for RTFd it's "com.apple.flat-rtfd".

Working with the Pasteboard, I found that when I (as an application user) copy rich text from a UITextView into cardboard, cardboard contains two types: "public.text", "Apple  In UIPasteboard Example, I have explained how to read data from UIPasteboard and write data to UIPasteboard and share data between apps. Pasteboard can be used to store Plain Text, Rich-Text, Image, Email,…etc.

UIPasteboard, episode we take a look at UIPasteboard, allowing us to inspect, copy, NSAttributedString(data: data, options: [:], documentAttributes: nil)  When I'm trying to copy a text from the FMP (FileMakerPro) and paste it to any textfield of my app, I'm getting asian symbols instead of copied text. It happens both when I'm launching a MacOS app, or an iOS app in the simulator. Seems like the FMP uses some kind of RTF the app cannot recognize.

Copy Text with Formatting, In typical usage, an object in your app writes data to a pasteboard when the user requests a copy, cut, or duplicate operation on a selection in the user interface. But what if you want to copy from an HTML source and maintain its color and formatting? Doing this requires creating an NSAttributedString from the HTML, then converting it into an NSData object, and then passing it to the UIPasteboard using a … Continue reading “Converting HTML to NSAttributedString, copy to Clipboard”

I'm assuming the correct approach is to copy an NSAttributedString to the pasteboard. body]]; UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];  We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand

Comments
  • Made some insights in UIPasteBoard and NSAttributedString, could be valuable: stackoverflow.com/a/38211885/1054573
  • @H2CO3 Thank you :) Updated the answer.
  • No use of DTCoreText. Convert this in HTML by this: NSDictionary *documentAttributes = [NSDictionary dictionaryWithObjectsAndKeys:NSHTMLTextDocumentType, NSDocumentTypeDocumentAttribute, nil]; \n NSData *htmlData = [attributedString dataFromRange:NSMakeRange(0, attributedString.length) documentAttributes:documentAttributes error:NULL]; \n NSString *htmlString = [[NSString alloc] initWithData:htmlData encoding:NSUTF8StringEncoding];
  • This is an iOS question.
  • Oops - that little "ios" tag is easy to overlook. And iOS doesn't appear to have RTF conversion built in. Bummer.
  • Agreed. Usually, when the tag is the only way to see it, I explicit it in the question. I didn't because I thought UIPasteboard would be enough. Sorry for not being more clear.
  • Oh, UIPasteboard. Yes, I could've noticed that one. I work so much on iOS and OSX that I keep confusing their slightly differently named classes all the time :)