New In iPhone 3.0 Tutorial Series, Part 3: Copy & Paste With UIPasteboard
This time, we’ll cover the basics of reading-from and writing-to the pasteboard.
There isn’t just one pasteboard on the iPhone:
There are two system pasteboards: a General system-wide pasteboard that’s used for copy-paste operations and a Find pasteboard that holds the last search string.
Additionally, applications can create their own pasteboards that can be used by other apps. For example, a point-of-sales app and a credit card terminal app could use a shared pasteboard to pass payment details back and forth.
An item added to the pasteboard has a type. More precisely, when an item is added to the pasteboard it has representations in one or more types. A web address, for example, could be stored as both a string and also a URL.
Storing multiple representations in the pasteboard allows for flexibility in how the item is used. An email client could use the text representation to plunk a readable NSString representation of the URL into the body of a message; a podcast app could consume the NSURL representation to fetch the podcast.
This approach isn’t unique to the iPhone. This design lets the same copy operation in Safari result in plain text in TextMate but formatted text in Pages.
Note: the examples in this tutorial will use the General pasteboard though, because all pasteboards ares subclasses of the
UIPasteboard class, the programming model applies to any pasteboard.
Using The General Pasteboard
generalPasteboard class method returns a pointer the general pasteboard — for these examples, I’ll have set the
pasteboard variable thusly:
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
The most common pasteboard operations involve getting or setting strings, images, URLs and colors. Apple provides convenience getters/setters for these in the form of properties:
NSString *string = pasteboard.string; UIImage *image = pasteboard.image; NSURL *url = pasteboard.URL; UIColor *color = pasteboard.color; pasteboard.string = @"paste me somewhere";
Determining If A Type Of Representation Is Available
The getter methods return nil if there isn’t a representation of the item in that type. It’s handy to know ahead of time whether a representation in a particular type is available. Use the
containsPasteboardTypes: method to check:
if ([pasteboard containsPasteboardTypes: [NSArray arrayWithObject:@"public.utf8-plain-text"]]) NSLog(@"String representation present: %@", pasteboard.string);
For a list of all the types for an item, use
Uniform Type Identifiers — UTIs — Signify Type
The previous example checked for the public.utf8-plain-text type to determine if a string was present. This is an example of a UTI, or Uniform Type Identifier. For info on UTIs, read Apple’s Uniform Type Identifiers Overview document.
Apple provides constants for common types in UTCoreTypes.h. To use the constants:
- Add the MobileCoreServices framework to your project
- #import <MobileCoreServices/MobileCoreServices.h>
The constants are of type
CFStringRef. You’ll work with them as NSStrings. The CFStringRef type is a fancy way of representing strings for both C and Objective-C. To use them in Objective-C simply cast them:
NSString *urlUTIType = (NSString *)kUTTypeURL;
You’re free to make up your own for your own data types; Apple recommends you use reverse-DNS notation style (e.g., com.mobileorchard.mySnazzyType) to ensure uniqueness.
Setting And Retrieving Types That Lack Convenience Getters/Setters
The convenience getters/setters are just a syntactic nicety. Essentially, they function the same as using the
NSString *string = [pasteboard valueForPasteboardType:@"public.utf8-plain-text"]; [pasteBoard setValue:@"paste me somewhere" forPasteboardType:@"public.utf8-plain-text"];
These methods are intended for strings, arrays, dictionaries, dates, numbers and URLs. The
setData:forPasteboardType: methods are available for other types.
Storing An Item With Multiple Representations
Using the convenience setters/properties has a significant limitation: items are stored with a single type. If, using our example from above, we want to store a URL as both a NSString as well as a NSURL we need to construct a dictionary of types and their values and set the pasteboard’s items property:
static NSString *string = @"https://www.mobileorchard.com"; NSDictionary *item = [NSDictionary dictionaryWithObjectsAndKeys: string, @"public.utf8-plain-text", [NSURL URLWithString:string], (NSString *)kUTTypeURL, nil]; pasteboard.items = [NSArray arrayWithObject:item];
pasteboard.url will return items.
Pasteboards Support Multiple Items
Note that, in the last example, we’re setting the items — plural — property. To keep this tutorial simple, I treated the pasteboard as a single-item entity. Should you require it, you can get/set arrays of items from the pasteboard. It’s generally straightforward to do so, usually involving little more than creating/consuming arrays pluralizing the property/method names. Check the docs for details.