New In iPhone 3.0 Tutorial Series, Part 3: Copy & Paste With UIPasteboard

By
On July 2, 2009

Welcome to part-3 of our New In iPhone 3.0 Tutorial/Programming Series. The previous two articles in this series covered in-app email and shake to undo/redo.

This time, we’ll cover the basics of reading-from and writing-to the pasteboard.

Pasteboard Overview

Multiple Pasteboards

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.

Multiple Representations

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.

Pasteboard Operations

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

The generalPasteboard class method returns a pointer the general pasteboard — for these examples, I’ll have set the pasteboard variable thusly:

UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];

Convenience Properties

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 pasteboardTypes.

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:

  1. Add the MobileCoreServices framework to your project
  2. #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 valueForPasteboardType: and setValue:forPasteboardType methods:

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 dataForPasteboardType and 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];

Now, both pasteboard.string and 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.

Mobile Orchard Beginning iPhone Programming Workshop. Bay Area, July 30-31. $999 early bird registration. Save $200 with “mo” discount code.

Comments are closed.