Mac OS X Reference Library Apple Developer
Search

Building a Text Editor in 15 Minutes

This article shows how you can use Cocoa to create a simple but highly capable text editor in less than 15 minutes using Xcode and Interface Builder. The Cocoa document architecture provides many of the features required for this type of application automatically, requiring you to write a minimal amount of code.

This tutorial uses Xcode version 3.2 and Interface Builder version 3.2 with Mac OS X version 10.6.

Here is a simplified summary of the steps needed to complete this task:

You can build and test the application at several stages of completion. The following steps expand and explain this procedure. The steps assume that you have a basic acquaintance with Xcode and Interface Builder.

Create the User Interface

This section shows how to use Xcode and Interface Builder to create the project and build its user interface.

  1. In Xcode, create a new project. Choose the Mac OS X template for a Cocoa application, and select the document-based application option.

  2. Open the MyDocument.xib file, in the Resources folder in the Groups & Files pane of the Xcode window, by double-clicking the MyDocument.xib icon, which launches Interface Builder. MyDocument.xib is the nib file containing the user interface for your NSDocument subclass, named MyDocument by the document-based application template.

  3. In the Window object, click the text field “Your document contents here” once and press the Delete key to delete the text field. (If you click twice, you begin editing its text content.) If the Library window is not already showing, choose Tools > Library. Click the Objects tab and navigate to Views & Cells > Inputs & Values.

    Select a text view as shown in Figure 1. Drag the text view onto the Window object. Resize the text view to almost fill the window, leaving margins as indicated by Interface Builder’s guide lines (which appear when the margins are correct).

    Figure 1  The Text View object selected in the Inputs & Values group

    Drag an NSTextView from the Cocoa Text Controls palette
  4. Click in the center of the view area and choose Tools > Size Inspector to open the inspector window. Ensure that the inspector window title reads “Scroll View Size.” Set the view to resize with the window by clicking both inner sets of crossed arrows in the Autosizing area, as shown in Figure 2. The inspector animation should indicate that the scroll view resizes with the window in both vertical and horizontal directions.

    Note:  Clicking in the center of the view area selects the scroll view containing the text view, as indicated by the title of the inspector window. Clicking inside the view area near the top selects the text view itself. Be sure to set the resize characteristics of the scroll view.

    Figure 2  Set the resize characteristics of the scroll view

    Set the resize characteristics of the scroll viewSet the resize characteristics of the scroll view
  5. Select the text view by clicking near the top of the view area. Choose Tools > Attributes Inspector (or click the Attributes tab of the inspector window), and ensure that the inspector window title reads “Text View Attributes.” Ensure that the Selection pop-up menu is set to Character and the Text Direction pop-up menu is set to Natural. Ensure that the following (default) options are selected: Editable, Selectable, Rich Text, Undo, Non-contiguous Layout, Draws Background, Find Panel, Font Panel, Ruler, Continuous Spell Checking, Smart Insert and Delete, and Autoresizes Subviews.

  6. Choose File > Simulate Interface, and resize the window to ensure that the text view resizes properly along with the window. Note that you can already edit text in the text view. When you drag the Text View object from the Library, Interface Builder automatically instantiates all the Cocoa text objects required for a complete editing and layout implementation. Choose Cocoa Simulator > Quit Cocoa Simulator to return to Interface Builder.

  7. Save the MyDocument.xib file and return to Xcode. Build and test the new application.

At this stage of your editor’s development, it has many sophisticated features. You can enter text, which you can then edit, cut, copy, and paste. You can find and replace text using the Find window. You can undo and redo editing actions. You can also format text, setting its font, size, style, and color attributes. You can control text alignment, justification, baseline position, kerning, and ligatures. You can display a ruler that provides a graphical interface to manipulate many text and layout attributes, as well as setting tab stops. You can even use the spelling checker.

In addition to its many editing features, your editor can open multiple documents, each with its own text view and contents. What it lacks most prominently are the abilities to open files and save text in files (that is, archiving and unarchiving documents). It also lacks such features as displaying its own icon in the Finder and presenting useful information in the About window.

Quit your new application before proceeding to the next section.

Implement Document Reading and Writing

This section explains how to enable your editor to open and save documents in files.

  1. Add an instance variable for the text view, so you can connect the text view with the code in your NSDocument subclass that handles archiving and unarchiving of documents in files. You also need to add an instance variable to hold the text string being edited (the document’s data model). In Xcode, put the variable declarations in MyDocument.h as follows:

    #import <Cocoa/Cocoa.h>
    @interface MyDocument: NSDocument
    {
        IBOutlet NSTextView *textView;
        NSAttributedString *mString;
    }
    @end
  2. Initialize the string instance variable. Put the following lines in the init method (which has a stub implementation) in MyDocument.m:

        if (mString == nil) {
            mString = [[NSAttributedString alloc] initWithString:@""];
        }
  3. Write getter and setter methods for the string instance variable. Put them in MyDocument.m as follows:

    - (NSAttributedString *) string { return [[mString retain] autorelease]; }
     
    - (void) setString: (NSAttributedString *) newValue {
        if (mString != newValue) {
            if (mString) [mString release];
            mString = [newValue copy];
        }
    }
  4. Add method declarations for the getter and setter methods, so that the header file MyDocument.h looks like this:

    #import <Cocoa/Cocoa.h>
    @interface MyDocument: NSDocument
    {
        IBOutlet NSTextView *textView;
        NSAttributedString *mString;
    }
    - (NSAttributedString *) string;
    - (void) setString: (NSAttributedString *) value;
    @end
  5. If it is not already open, double-click MyDocument.xib to open the document window in Interface Builder. From Xcode, drag the MyDocument.h file icon onto the document window of MyDocument.xib. This step informs the MyDocument.xib file that the MyDocument object interface now has an outlet variable named textView.

  6. In the document window of Interface Builder, double-click the Window icon to open the Window object. Open the inspector. In the Window object, click inside the view area at the top to select the text view object. Be sure you select the text view object and not its containing scroll view object, as indicated by the title of the inspector window.

  7. Connect the textView outlet of the File's Owner (that is, the MyDocument object) by Control-dragging from the File's Owner icon in the document window of MyDocument.xib to the text view, which is selected in the window, as shown in Figure 3. When the connection is made, Interface Builder displays a list of prospective outlets under the mouse pointer. Click the textView outlet. (Alternatively, you can select the File’s Owner icon in the document window and use the Connections tab of the inspector to make the connection by dragging from the circle opposite the textView outlet to the text view selected in the Window object.)

    Figure 3  Connect the text view outlet of the File's Owner

    Connect the text view outlet of the File's OwnerConnect the text view outlet of the File's Owner
  8. In Interface Builder, make the File’s Owner (that is, the MyDocument object) the delegate of the text view. Select the text view in the Window object and Control-drag from the text view to the File’s Owner icon, as shown in Figure 4. When the connection is made, Interface Builder displays the text view’s outlets under the mouse pointer. Click the delegate outlet. (Alternatively, you can select the text view in the Window object and use the Connections tab of the Inspector to make the connection by dragging from the circle opposite the delegate outlet to the File’s Owner icon, which is selected in the document window.)

    Figure 4  Connect the delegate of the text view

    Connect the delegate of the text viewConnect the delegate of the text view
  9. Implement the text view’s delegate method textDidChange: in MyDocument.m to synchronize the text string in the document’s data model (the mString instance variable) with the text storage belonging to the text view, whenever the user changes the text.

    - (void) textDidChange: (NSNotification *) notification
    {
        [self setString: [textView textStorage]];
    }
  10. Implement document reading and writing methods. When you initially created the project, Xcode placed stubs for these methods in MyDocument.m. Fill in the method bodies as follows:

    - (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
    {
        BOOL readSuccess = NO;
        NSAttributedString *fileContents = [[NSAttributedString alloc]
                    initWithData:data options:NULL documentAttributes:NULL
                    error:outError];
        if (fileContents) {
            readSuccess = YES;
            [self setString:fileContents];
            [fileContents release];
        }
        return readSuccess;
    }
     
    - (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
    {
        NSData *data;
        [self setString:[textView textStorage]];
        NSMutableDictionary *dict = [NSDictionary dictionaryWithObject:NSRTFTextDocumentType
                                            forKey:NSDocumentTypeDocumentAttribute];
        [textView breakUndoCoalescing];
        data = [[self string] dataFromRange:NSMakeRange(0, [[self string] length])
                            documentAttributes:dict error:outError];
        return data;
    }
  11. Add three lines of code to the windowControllerDidLoadNib: method to place the contents of the window’s data model into the text view when the window’s nib file is initially loaded. Leave the call to the superclass windowControllerDidLoadNib: method and add the following lines after it:

    if ([self string] != nil) {
        [[textView textStorage] setAttributedString: [self string]];
    }
  12. Build and test your application.

Your editor should now be able to save documents that you create to files, and it should be able to open those documents again and continue editing them. If you attempt to close a document that has been changed since it was last saved, the editor should display a warning dialog and let you save the document.

At this stage of its development, your editor opens and saves documents only with an extension of ????. To enable your application to save and open documents with a recognized file type, you need to use Xcode to configure the document types settings in the application’s property list file in the Resources folder in Xcode. (The Xcode template names the file with your project name followed by -Info.plist.) You can edit this file in Xcode by selecting the file in the Groups & Files list and using the built-in editor. Click the disclosure triangles to edit the value of the first item under CFBundleTypeExtensions to the preferred extension for your document files.

For more information about property list files, see “Storing Document Types Information in the Application's Property List” in Document-Based Applications Overview. For complete details about application property lists, see Runtime Configuration Guidelines.

You can also specify your application’s icon file in the application’s Info.plist file. You can add useful information to be displayed in the About box by editing the Credits.rtf file in the Resources folder in Xcode.

For more examples of Cocoa text applications, refer to the Sample Code resource type of the Mac OS X Reference Library. You can find text-related examples in the Data Management and User Experience topics.




Last updated: 2009-11-30

Did this document help you? Yes It's good, but... Not helpful...