6.2 URL Resources

Foundation has two classes that facilitate working with URLs: NSURL and NSURLHandle. NSURL represents a Uniform Resource Locator (URL). This class lets applications create, manipulate, and pick apart URLs. NSURLHandle accesses data and resources specified by an instance of NSURL. This class can access resources provided by HTTP, FTP,[1] and file services.

[1] FTP support in NSURLHandle was added in Mac OS X 10.2 and is not available in earlier versions of Mac OS X.

6.2.1 Working with URLs

NSURL represents a URLthe human-readable host names and paths that various network clients use to locate resources on the local filesystem or over the Internet. NSURL provides a number of methods and initializers that let you create instances in many different ways, as shown in Example 6-2.

Core Foundation has a type, CFURL, that is "toll-free bridged" to NSURL. As such, the two types can be used interchangeably. CFURL and NSURL are essentially equivalent: NSURL objects can be used in Core Foundation calls that ask for a CFURL, and vice versa. NSURL is just one of several Foundation classes that have a bridged Core Foundation equivalent.

Example 6-2. Creating and initializing instances of NSURL
// From a string...
NSURL *url = [NSURL URLWithString:@"http//www.macdevcenter.com"];
url = [[NSURL alloc] 
         initWithString: :@"http//www.macdevcenter.com"];

// From a file path...
url = [NSURL fileURLWithPath:@"/Users/mike/Pictures/pic.tiff"];
url = [[NSURL alloc] 
    initFileURLWithPath: :@"/Users/mike/Pictures/pic.tiff"];

// Access a URL with scheme, host, and path
url = [[NSURL alloc] initWithScheme:@" FTP" host:@"localhost"

In Example 6-2, the last initializer, initWithScheme:host:path:, specifies the scheme used by the host the URL points to. In this case, an FTP address was specified; however, the backend to NSURL's data transfer functionality, NSURLHandle, supports HTTP and file URL schemes as well.

NSURL includes an assortment of methods that let you pick apart URLs to extract pieces of information from them, such as the URL path, the host name, the base URL, and the query string. Example 6-3 illustrates several NSURL methods.

Example 6-3. NSURL methods
NSURL *url = [NSURL URLWithString:@"http//www.google.com/

NSString *s;
s = [url host];                    // Returns "www.google.com"
s = [url scheme];                  // Returns "HTTP"
s = [url path];                    // Returns "/search"

// Returns "//www.google.com/search?hl=en&ie=ISO-8859-1&q=NSURL&btnG=Google+Search"
s = [url resourceSpecifier];

// Returns "hl=en&ie=ISO-8859-1&q=NSURL&btnG=Google+Search"
s = [url query];

While NSURLHandle implements data transfer functionality, NSURL provides a handful of convenience methods that can transfer data without having to instantiate NSURLHandle. These methods, whose usage is shown in Example 6-4, include:

  • resourceDataUsingCache:

  • setResourceData:

  • loadResourceDataNotifyingClient:usingCache:

Example 6-4. Using NSURL data access methods
// Create an instance of NSURL from an NSString
NSString *urlStr = @"http//host_address/image.jpg";
NSURL *url = [NSURL URLWithString:urlStr];

// Download data from the resource located by a URL
NSData *data = [url resourceDataUsingCache:NO];
NSImage *img = [[NSImage alloc] initWithData:data];

// Write data to a resource located by a URL
NSData *data = [img TIFFRepresentation];
[url setResourceData:data];

If YES is passed to the resourceDataUsingCache: method, NSURL attempts to load the resource from the cache if it was loaded previously. If the resource was not loaded, then the host will load it. Passing NO to this method tells NSURL to always fetch the data from the host, even if it has done so already.

Many Cocoa classes that work with files have methods that let clients interact with files through standard file paths or URLs. For example, you could have replaced the middle two lines of code in Example 6-4 with NSImage's initializer initWithContentsOfURL:, supplying url as the argument.

6.2.2 URL Handles

NSURLHandle provides an interface for uploading and downloading data to and from a resource specified by an instance of NSURL. NSURLHandle actually offloads much of this work to subclasses that implement NSURLHandle's interface to work with various schemes. NSURLHandle's subclasses include NSFileURLHandle, NSFTPURLHandle, and NSHTTPURLHandle. These three subclasses are privateall interaction with them is through NSURLHandle's public interface, which creates the proper subclass based on the provided NSURL object's scheme. For most purposes, the interface provided by NSURL should be sufficient for resource access. NSURLHandle is most useful when you need to create a new subclass to support a URL scheme other than file, FTP, or HTTP. Managing subclasses

NSURLHandle's subclasses are responsible for implementing the resource acquisition mechanics needed by a URL scheme. When created, that subclass needs to be registered with NSURLHandle using the class method registerURLHandleClass:. The registration process makes NSURLHandle aware of a subclass's availability to handle a new URL scheme.

To determine whether NSURLHandle handles a particular URL scheme, use the class method canInitWithURL:. Additionally, you can retrieve the actual class object used by NSURLHandle for a particular URL scheme by invoking the class method URLHandleClassForURL:.

    Part II: API Quick Reference