TweetFollow Us on Twitter

Using NSParagraphStyle

Volume Number: 19 (2003)
Issue Number: 8
Column Tag: Cocoa

Using NSParagraphStyle

How to programmatically set tabs and more in an NSTextView

by Clark Jackson

The need to become acquainted with NSParagraphStyle occurred when I attempted to automate some reporting. At times "enterprise" computing stands in contrast to typical "consumer" computing because the latter is user-centric while the former is report-centric. For example, consumer computing facilitates lots of user control whereas enterprise computing just wants to-generate-reports-unattended-at-midnight-thank-you. Since much of the text system in Cocoa "just works" for the user, the details of how to let the computer take control in making a report are often left a mystery. Let's shed a little light on some of that mystery.

What we need is to know how to use just one piece of Cocoa's extensive and capable text system that will allow a program to format text inside an NSTextView. The key is using the NSParagraphStyle class.

Some preliminaries

Explaining Interface Builder and Project Builder is beyond the scope of this article. Suffice it to say, the project uses the Model-View-Controller paradigm employing MyModel, MyWindowController, and NSTextView classes. Here's what the view looks like:

Figure 1. The interface window containing an NSTextView.

The only thing noteworthy about this window is that it contains an NSTextView because that is where our formatted text will appear.

To see the results of our formatting it will be useful to use NSTextView's ruler. To see the ruler it is necessary to add the Format menu to our menu bar. Therefore, before leaving IB, we drag the Format menu onto our project's main menu bar and give Show Ruler a key equivalent:

Figure 2. For convenience, in Interface Builder we drag a Format menu onto the menu bar and give Show Ruler a key equivalent.

The view

For our purposes, the important thing to know about NSTextView is that the text displayed in an NSTextView is its textStorage and that textStorage holds attributed strings. The textStorage is an instance of NSTextStorage which inherits from NSAttributedString itself. Attributed strings are Cocoa Foundation objects that contain both ordinary NSString's and formatting objects that apply to those strings, for example, NSFont and NSParagraphStyle. You can bypass dealing with NSTextView's textStorage directly, that is, you can [myNSTextView setString:@"aString"], but @"aString" will adopt either the default paragraph style or a previous style already residing in the textStorage.

Therefore, in order for text to appear formatted in an NSTextView we have to: 1) create an NSAttributedString instance initialized with the string we want to format, and 2) give that NSAttributedString instance the objects that it will use to format the string-in this case an NSParagraphStyle object. This attributed string goes into our NSTextView's textStorage where it appears formatted to the user.

The Controller

The interface buttons are connected to the controller's actions in a typical fashion. Basically, each button initiates a controller action to display a different formatted paragraph in the NSTextView. The controller does this task by sending a string (NSString) to the model object. The model object will return attributed strings (NSAttributedString's attributed with NSParagraphStyle's) to the controller. Finally, the controller will pass the attributed string to the text storage of the NSTextView where it will appear formatted to the user.

Here is one of the three controller actions:


This method sets a pattern for the other two belonging to the controller. An unformatted string is 
put in the NSTextView for comparison purposes only. The program pauses so the user can see it. Next, 
the string is sent to the model object which returns it as an attributed string. Finally, the 
attributed string goes into the NSTextView revealing the new format. Refer to the source to see the 
other two action methods, applyStyle2 and applyStyle3. 

- (IBAction)applyStyle1:(id)sender
   MyModel *theModel;
   NSAttributedString *anAttString;
   NSString *aString;
   // a string containing multiple paragraphs
   aString = @"On a merry-go-round in the night, ";
   aString = [aString stringByAppendingString:
      @"Coriolis was shaken with fright.\n"];
   aString = [aString stringByAppendingString:
      @"Despite how he walked, "];
   aString = [aString stringByAppendingString:
      @"'Twas like he was stalked,\n"];
   aString = [aString stringByAppendingString:
      @"By some fiend always pushing him right."];
// limerick by David Morin, Eric Zaslow, E'beth Haley, John Golden, and Nathan Salwen,
   // a convenience method to restore the default paragraph style to the NSTextView
   [self resetTextView]; 
   // install string w/o changing paragraph style for comparison
   [myNSTextView setString:aString]; 
   [myNSTextView display]; // force redraw
   sleep(1); // pause
   // now convert aString to an NSAttributedString by applying an NSParagraphStyle
   //   using the model object
   theModel = [[MyModel alloc]init];
   anAttString = [theModel attributeString1:aString];
   [theModel release];
   // now that we have the attributed string, put it into the NSTextView.
   // In order to get multiple attributed strings into a textStorage use
//      [myNSTextView insertText:attributedString] instead
   [[myNSTextView textStorage]
   [myNSTextView setNeedsDisplay:YES];

The Model

MyModel has a method for each of the controller's actions. It is here that we make use of NSParagraphStyle. Each method takes an ordinary NSString and returns it as an NSAttributedString so it can end up formatted in the NSTextView. When running the program, click inside the NSTextView and make the ruler visible. Some of the paragraph style attributes that we set show up on the NSTextView's ruler:

Figure 3. Many of NSParagraphStyle attributes appear in the NSTextView ruler.

Following are the methods used to create NSParagraphStyle's and apply them to strings thus creating NSAttributedString's:


This method creates an NSMutableAttributedString, using an NSString and an NSMutableParagraphStyle.

-(NSMutableAttributedString *) attributeString1:
      (NSString *) aString
   NSMutableParagraphStyle *aMutableParagraphStyle;
   NSMutableAttributedString   *attString;
   The only way to instantiate an NSMutableParagraphStyle is to mutably copy an
   NSParagraphStyle. And since we don't have an existing NSParagraphStyle available
   to copy, we use the default one.
   The default values supplied by the default NSParagraphStyle are:
      Alignment   NSNaturalTextAlignment
      Tab stops   12 left-aligned tabs, spaced by 28.0 points
      Line break mode   NSLineBreakByWordWrapping
      All others   0.0
   aMutableParagraphStyle =
      [[NSParagraphStyle defaultParagraphStyle]mutableCopy];
   // Now adjust our NSMutableParagraphStyle formatting to be whatever we want.
   // The numeric values below are in points (72 points per inch)
   [aMutableParagraphStyle setLineSpacing:5.5];
   [aMutableParagraphStyle setParagraphSpacing:25.5];
   [aMutableParagraphStyle setHeadIndent:25.0];
   [aMutableParagraphStyle setTailIndent:-45.0];
   // setTailIndent: if negative, offset from right margin (right margin mark does
   //      NOT appear); if positive, offset from left margin (margin mark DOES appear)
   [aMutableParagraphStyle setFirstLineHeadIndent:65.0];
    possible allignments
    possible line wraps
   // Instantiate the NSMutableAttributedString with the argument string
   attString = [[NSMutableAttributedString alloc]
   // Apply your paragraph style attribute over the entire string
   [attString addAttribute:NSParagraphStyleAttributeName
      range:NSMakeRange(0,[aString length])];
   [aMutableParagraphStyle release]; // since it was copy'd
   [attString autorelease]; // since it was alloc'd
   return attString;

If your NSTextView already has attributed strings in its textStorage, you can get the NSParagraphStyle by:

aMutableParagraphStyle = [[myTextView typingAttributes]

The NSParagraphStyle returned above comes from the attributes of the text from where the cursor is found inside the NSTextView. NSParagraphStyle's can span multiple paragraphs but there cannot be more than one per paragraph.


This method creates an array of NSTextTab's and applies them to the NSMutableParagraphStyle before 
it is used to create the NSMutableAttributedString.

-(NSMutableAttributedString *)
   attributeString2:(NSString *) aString
   float firstColumnInch = 1.75,
      otherColumnInch = 0.6, pntPerInch = 72.0;
   int i;
   NSTextTab *aTab;
   NSMutableArray *myArrayOfTabs;
   NSMutableParagraphStyle *aMutableParagraphStyle;
   NSMutableAttributedString   *attString;
   myArrayOfTabs = [NSMutableArray arrayWithCapacity:14];
   aTab = [[NSTextTab alloc]
   [myArrayOfTabs addObject:aTab];
   [aTab release]; // aTab was alloc'd and the array owns it now so release it
      aTab = [[NSTextTab alloc]
         + ((float)i * otherColumnInch * pntPerInch)];
      [myArrayOfTabs addObject:aTab];
[aTab release]; // aTab was alloc'd and the array owns it now so release it
   possible tab stop types
   aMutableParagraphStyle =
      [[NSParagraphStyle defaultParagraphStyle]mutableCopy];
   [aMutableParagraphStyle setTabStops:myArrayOfTabs];
   attString = [[NSMutableAttributedString alloc]
   [attString addAttribute:NSParagraphStyleAttributeName
      range:NSMakeRange(0,[aString length])];
   [aMutableParagraphStyle release];
   [attString autorelease];
   return attString;

Tabbed text appears as below without using NSParagraphStyle:

Figure 4. Default behavior of an NSTextView containing tabbed text. The tab spacing is arbitrary and the lines wrap even though there is space enough to hold the whole line.

Tabbed text appears as below after creating an NSMutableParagraphStyle and assigning it to an NSMutableAttributedString using the attributeString2 method:

Figure 5. By using an NSMutableParagraphStyle the tab stops have been precisely set and the lines do not wrap unexpectedly.


This method supplies a way to parse a string containing multiple paragraphs and apply different 
paragraph styles to each.

-(NSMutableArray *) attributeString3:(NSString *)aString 
   NSRange myRange,rangeOfLine,rangeOfLineContent;
   unsigned startIndex,lineEndIndex,contentsEndIndex;
   NSMutableAttributedString   *attString;
   int lineCtr;
   NSMutableArray * arrayOfNSMutableAttributedString;
   NSString *pulledOutParagraph;
      = [NSMutableArray arrayWithCapacity:5];
    lines can be terminated in the following ways for use with
    *    U+000D (\r or CR), Mac
    *    U+2028 (Unicode line separator)
    *    U+000A (\n or LF), Unix
    *    U+2029 (Unicode paragraph separator)
    *    \r\n, in that order (also known as CRLF), Windows
   Using getLineStart:end:contentsEnd:forRange: 
   @"Big\r\nMac    --example string
   in this case
      1st contentsEndIndex    is set to 3,
         the first character past the line content,
         line content being defined as the characters not including
         line termination character(s)
      1st lineEndIndex    is set to 5
         the first character past the end of line character(s)
   // make 2 different paragraph styles
   aMutableParagraphStyle1 =
      [[NSParagraphStyle defaultParagraphStyle]mutableCopy];
   aMutableParagraphStyle2 =
      [[NSParagraphStyle defaultParagraphStyle]mutableCopy];
   // initialize
   myRange = NSMakeRange(0,0); // (location,length)
   lineEndIndex = 0;
   lineCtr = 0;
    The while() block below walks down the string pulling out lines (paragraphs)
   including their end of line (paragraph) characters, converts them to attributed strings,
   and adds them to an array.
   The range in the getLineStart:end:contentsEnd:forRange: method has to be picky
   about where it's location is but doesn't have to be picky about length (i.e. 0 will do)
   while(lineEndIndex < [aString length])
      [aString getLineStart: &startIndex
         end: &lineEndIndex
         contentsEnd: &contentsEndIndex
         forRange: myRange];
      // rangeOfLineContent excludes line termination character(s)
      rangeOfLineContent =
      // rangeOfLine includes line termination character(s)
      rangeOfLine =
      // apply paragraph style to pulledOutParagraph
      pulledOutParagraph =
         [aString substringWithRange:rangeOfLine];
      attString = [[NSMutableAttributedString alloc]
      if(lineCtr % 2 == 0) // alternate paragraph styles on odd/even lines
         // If range.length below is zero then the paragraph style is not applied.
         //   For strings with length > 0, range.length should be > 0 and <= length of the
         //   string so NSMakeRange(0,1) would work as well below
         //   provided you don't have an empty string.
         [attString addAttribute:NSParagraphStyleAttributeName
            value: aMutableParagraphStyle1
            range: NSMakeRange(0,[pulledOutParagraph length])];
         [attString addAttribute:NSParagraphStyleAttributeName
            range:NSMakeRange(0,[pulledOutParagraph length])];
      [arrayOfNSMutableAttributedString addObject:attString];
      [attString release]; // the array now owns it
      // recalculate the range before looping
      myRange = NSMakeRange(lineEndIndex,0); 
   [aMutableParagraphStyle1 release];
   [aMutableParagraphStyle2 release];
   return arrayOfNSMutableAttributedString;


Cocoa's text system is extensive involving many classes not even mentioned here. But if you just need to get some formatted, tabbed text into an NSTextView for that special report, the methods explained here should do the trick.

Clark Jackson test drove the first Mac and recognized that it was about to change the world. Lately he has been busy wearing many hats automating energy accounting in the rapidly changing electrical power industry at Tacoma Power. He can be contacted at


Community Search:
MacTech Search:

Software Updates via MacUpdate

Adobe Acrobat Reader 15.009.20069 - View...
Adobe Acrobat Reader allows users to view PDF documents. You may not know what a PDF file is, but you've probably come across one at some point. PDF files are used by companies and even the IRS to... Read more
Adobe Acrobat Pro 15.009.20069 - Powerfu...
Acrobat Pro DC is available only as a part of Adobe Creative Cloud, and can only be installed and/or updated through Adobe's Creative Cloud app. Adobe Acrobat Pro DC with Adobe Document Cloud... Read more
Path Finder 7.2 - Powerful, award-winnin...
Become a master of file management with Path Finder. Take full control over your file system. Save your time: compare and synchronize folders, view hidden files, use Dual Pane and full keyboard... Read more
Sid Meier's Civilization: Beyond Ea...
Sid Meier's Civilization: Beyond Earth is a new science-fiction-themed entry into the award-winning Civilization series. Set in the future, global events have destabilized the world leading to a... Read more
ForkLift 2.6.6 - Powerful file manager:...
ForkLift is a powerful file manager and ferociously fast FTP client clothed in a clean and versatile UI that offers the combination of absolute simplicity and raw power expected from a well-executed... Read more
Microsoft Remote Desktop 8.0.21 - Connec...
With Microsoft Remote Desktop, you can connect to a remote PC and your work resources from almost anywhere. Experience the power of Windows with RemoteFX in a Remote Desktop client designed to help... Read more
OnyX 3.1.0 - Maintenance and optimizatio...
OnyX is a multifunctional utility for OS X. It allows you to verify the startup disk and the structure of its System files, to run miscellaneous tasks of system maintenance, to configure the hidden... Read more
Spotify - Stream music, crea...
Spotify is a streaming music service that gives you on-demand access to millions of songs. Whether you like driving rock, silky R&B, or grandiose classical music, Spotify's massive catalogue puts... Read more
ExpanDrive - Access cloud storag...
ExpanDrive builds cloud storage in every application, acts just like a USB drive plugged into your Mac. With ExpanDrive, you can securely access any remote file server directly from the Finder or... Read more
Markly 1.5.3 - Create measurement and de...
Markly is a measurement and design-spec plugin/extension for Photoshop and Sketch. It is made for modern Web designers and app front-end developers. You can add specification marks simply by clicking... Read more

Max Ammo - Tricks and tips to help you l...
Max Ammo is a smart cover shooter in which you have to fight back against the Reptor Empire, a race of alien lizards who have invaded your home. You'll have to tap to shoot, swipe to get into cover, and upgrade your gear if you plan on surviving... | Read more »
Balls & Holes - Tips and tricks to h...
Balls & Holes is a gorgeous new endless runner that challenges you to make it as far up a mountain as possible before inevitably being sliced into a load of gooey bits. Making this task more difficult are both the wide variety of balls that... | Read more »
Balloony Land offers a fresh twist on th...
Balloony Land by Palringo offers a fresh twist on the match three genre and is out now on iOS and Android. First-off, you'll be popping balloons instead of crushing candy and the balloons will float up and fill the empty spaces instead of dropping... | Read more »
Graphic - vector illustration and design...
Graphic - vector illustration and design 1.0 Device: iOS iPhone Category: Productivity Price: $2.99, Version: 1.0 (iTunes) Description: Autodesk Graphic is a powerful full-featured vector drawing and illustration application right in... | Read more »
Sago Mini Babies (Education)
Sago Mini Babies 1.0 Device: iOS Universal Category: Education Price: $2.99, Version: 1.0 (iTunes) Description: Introducing the Sago Mini babies. Boys and girls love caring for these adorable characters. Feed Robin her favorite mush... | Read more »
PAUSE - Relaxation at your fingertip (H...
PAUSE - Relaxation at your fingertip 1.1 Device: iOS iPhone Category: Healthcare & Fitness Price: $1.99, Version: 1.1 (iTunes) Description: | Read more »
Super Sharp (Games)
Super Sharp 1.1 Device: iOS Universal Category: Games Price: $1.99, Version: 1.1 (iTunes) Description: Your finger has never been so sharp! Cut with skill to complete the 120 ingenious physics levels of Super Sharp and become a cut... | Read more »
Assembly - Graphic design for everyone...
Assembly - Graphic design for everyone 1.0 Device: iOS Universal Category: Photography Price: $2.99, Version: 1.0 (iTunes) Description: Assembly is the easiest most powerful design tool on the App Store. Create anything you can... | Read more »
Dub Dash (Games)
Dub Dash 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: ARE YOU READY FOR THE ULTIMATE CHALLENGE? UNIQUE SYMBIOSIS OF MUSIC AND GRAPHICS | Read more »
Leave Me Alone (Games)
Leave Me Alone 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: 33% off launch sale!!! Somewhere between the 1980s and 1990s there exists a world that never was. A world of skatepunks,... | Read more »

Price Scanner via

Adobe and Dropbox Partner to Streamline Work...
Adobe and Dropbox Inc. have announced a partnership to enable people and organizations greater flexibility to work the way they want with documents at home, in the office or on-the-go. The companies... Read more
DriveSavers Offers Data Recovery Relief to Vi...
DriveSavers, specialists in data recovery, eDiscovery and digital forensic services have announced assistance to victims of the recent storm and historically unprecedented flooding in South Carolina... Read more
Apple Products Four Of 2015′s Top Ten Most Wa..., Future’s global technology brand and the UK’s biggest technology website, has unveiled results from extensive research that show • The Smart Home is what excites the public most about... Read more
13-inch 2.7GHz/128GB Retina MacBook Pro on sa...
Best Buy has the 13″ 2.7GHz/128GB Retina MacBook Pro on sale for $1174.99 for a limited time. Choose free shipping or free local store pickup (if available). Sale price for online orders only, in-... Read more
App Tamer 2.1 Makes El Capitan Cooler, Quiete...
St. Clair Software has announced the availability of a free update to its App Tamer utility for Mac OS X. App Tamer 2.1 delivers compatibility with Yosemite and improves its support for a number of... Read more
15-inch Retina MacBook Pros on sale for up to...
B&H Photo has 2015 15″ Retina MacBook Pros on sale for up to $160 off MSRP including free shipping plus NY sales tax only: - 15″ 2.2GHz Retina MacBook Pro: $1849.99 $150 off - 15″ 2.5GHz Retina... Read more
12-inch Retina MacBooks on sale for $100 off...
Best Buy has 12″ Retina MacBooks available for $100 off MSRP on their online store. Choose free shipping or free local store pickup (if available). Discounted prices available for online orders only... Read more
MacBook Airs on sale for up to $100 off MSRP
Save up to $100 on the purchase of a new 2015 13″ or 11″ 1.6GHz MacBook Air at the following resellers. Shipping is free with each model: 11" 128GB MSRP $899 11" 256GB... Read more
Save 15% with Apple refurbished Mac Pros
The Apple Store has Apple Certified Refurbished Mac Pros available for up to $600 off the cost of new models. An Apple one-year warranty is included with each Mac Pro, and shipping is free. The... Read more
Apple restocks refurbished Mac minis for up t...
Apple has restocked Certified Refurbished 2014 Mac minis, with models available starting at $419. Apple’s one-year warranty is included with each mini, and shipping is free: - 1.4GHz Mac mini: $419 $... Read more

Jobs Board

*Apple* Desktop Analyst - KDS Staffing (Unit...
…work with some of the brightest engineers. Job Description Title: Apple Desktop AnalystPosition Type: Full-time PermanentLocation: White Plains, NYHot Points:Depth of Read more
*Apple* Systems Engineer (Mclean, VA and NYC...
Title: Apple Systems Engineer (Mclean, VA and NYC) Location: United States-New York-New York-NYC 200 Park Avenue (22005) Other Locations: United Read more
Partner Business Development Manager - *Appl...
…exceptional individuals to join our Sales Solutions team as Business Development Manager- Apple . This position focuses on the overall management of and achievement of Read more
Project Manager: *Apple* Pay - Apple (Unite...
…The iOS Systems team is looking for a project manager who will manage Apple Pay server side integration project resources in a matrix organization, track tasks, prepare Read more
*Apple* Retail - Multiple Positions (US) - A...
Job Description:SalesSpecialist - Retail Customer Service and SalesTransform Apple Store visitors into loyal Apple customers. When customers enter the store, you're Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.