This section lets you look at data storage tools other than documents. Like documents, they are all ways to persist data from your apps, and all of these tools, including documents, are supported on Cocoa and Cocoa Touch. Many of the tools (including the ones in this part of the book) have long histories in Cocoa and its predecessors. As noted, documents have evolved over time and have changed in many ways. The tools in this section have certainly changed over time, but the basic structures have remained remarkably stable so they are used in many legacy apps as well as in ones being developed today.
All of the tools in this chapter let you combine files into multi-file structures that can be manipulated either as single structures or as their component parts.
Using Packages
From early days of Macintosh, multi-file packages have been used to manage files. In the first Macintosh file system , files had two sections called forks. Almost all files had a data fork, and many files also had a resource fork. The user-visible file was basically the data fork, and the resource fork contained elements that the data fork used. These elements were typically alerts, icons, and other identifiable or visible elements. Each type of element in a resource fork had a name, typically a four-character code such as ALRT (for alert), DLOG (for dialog), or ICON. The idea of using identifiable and structured elements in a container remains a critical part of Cocoa.
The disadvantage of the resource fork was that when you copied a file to another platform the resource fork typically disappeared; it was the data fork that contained the data so it wasn’t a disaster in most cases. Today, Cocoa (and Cocoa Touch) use a more sophisticated way of wrapping data into what appears to be a single file. They are referred to as packages.
Note
Swift packages are manifests that are used to assemble code and manage dependencies. A common tool is CocoaPods ( CocoaPods.org ).
Note that not all files or folders are packages, so the Control key cannot open them. However, it is important to note that your Xcode project is a package of files. If you move the folder away from the xcodeproj file that refers to it, you will break the project package.
Considering Bundles
When you add files to an app in the project navigator, they are usually automatically added to the Build Phases step so that they are found in the app bundle, and that’s where you can retrieve them from in your code. By default, your app has a main bundle (bundle.main) with known contents. You can find the API at developer.apple.com by looking for bundle.
Using File Wrappers
Note that you need to set the LSTypeIsPackage property to YES so that the document appears to the user as a single object. The file type should conform to com.apple.package.
You can download WrapperPlaygroundDemo as described in Chapter 1 to see how to put a file wrapper document together. The process is described in the following section. The code is shown in Listing 10-1.
Assemble the files that will be wrapped.
Convert each file to the Data type (formerly NSData). There are utility methods in Swift to do this easily.
Wrap each file in a wrapper.
Create a root wrapper in the document.
Add each wrapped file to the root wrapper.
You can do these steps in any order, and there are functions that let you add and remove them dynamically. One common use of file wrappers is to wrap together several related files such as media and text. If they are wrapped in a file wrapper, you use the contents(forType:) and load(fromContents:ofType:) methods as you would for a document that consists of any data type such as an archive or a single image or text.
The files in the root file wrapper are not in any given order. Most important for reasons of efficiency is the fact that each file wrapper is loaded separately so if you have a lot of files in a single object, you can load them on an as-needed basis (Swift and Cocoa take care of this for you).
Assembling a File Wrapper Document in a Playground
Summary
This chapter showed how to wrap files together in bundles or file wrappers. There are efficiencies to using file wrappers since only necessary file wrappers are updated as the root file wrapper is managed. The overall idea of having a way to handle files separately or together depending on what you want to do with them is the key take-away from wrappers and bundles.