Loading means that there is already a file on the computer’s disk that we want to read and use in an application. Writing the code to load a file is usually considerably easier than writing the code to save it, because the hard work of figuring out which instance variables to save and getting them on the disk has (presumably) already been done.
A user can load a file into the MathPaper application by doing any of the following:
Choosing MathPaper’s File → Open menu command and specifying a file in the Open panel
Choosing a file from MathPaper’s File → Open Recent submenu
Double-clicking a MathPaper document file icon in the Finder
Dragging a MathPaper document on top of the
MathPaper.app
application icon and dropping it
The NSDocument framework handles all of these file-opening techniques for us automatically! All we need to do is to implement a single method called loadDataRepresentation:ofType: .
Insert the following loadDataRepresentation:ofType method into the
implementation of the MathController class in the file
MathController.m
:
- (BOOL)loadDataRepresentation:(NSData *)newHistory ofType:(NSString *)aType { if ([aType isEqualToString:@"MathPaper"]) { MathDocument *temp; temp = [NSUnarchiver unarchiveObjectWithData:newHistory]; if (temp) { [self setFrame:[temp frame] ]; [self setHistory:[temp history] ]; return YES; } } return NO; }
When any of the actions described at the beginning of this section
take place, the NSDocument architecture will open the requested file,
copy the file’s data into the NSData object, and
then pass this object and the document file type to our method. Our
method makes sure that the NSData object is of the correct type. If
it is, we ask the NSUnarchiver class to unarchive the NSData object
into a temporary MathDocument object called temp
.
If the load is successful, the instance variables
frame
and history
are set from
the unarchived object. (We need to do this two-stage process because
we decided to use the MathDocument class itself as the repository for
the information in the document, rather than using a separate class
created for that purpose.)
Unarchiving is the reverse of archiving: the NSUnarchiver class reads bytes from the NSData object and creates integers, floating-point values, and objects. Just as the NSArchiver class called the method encodeWithCoder: to perform the actual archiving, the NSUnarchiver class calls the method initWithCoder: to perform the actual unarchiving. Thus, in order to support unarchiving, we need to implement initWithCoder: as well.
At this point, note the following important things. First, the MathPaper instance variables are decoded in the same order in which they were encoded. This is very important! If you’re trying to decode the variables in a different order, the decoding operation will generate an error. (In fact, an exception will be raised. You will not get corrupt data, as you might on other systems.)
Second, note that the history object is sent a retain message. Objects that are decoded are sent an autorelease message so that they will be freed when they are no longer needed; it is the responsibility of the class implementation to retain objects that are required for long-term use.
What happens if you save a MathPaper window in the upper-right corner when your screen resolution is set to something like 1280 x 1024, and then you attempt to read it back in at a different resolution, such as 1024 x 768? On some other operating systems, such as Microsoft Windows, you might discover that the window is “off the screen” and unusable. However, Cocoa looks at the size of the window whenever you call itssetFrame:display: method, and tries to keep windows on the computer’s screen.
18.223.213.238