Home > Articles > Software Development & Management

This chapter is from the book

This chapter is from the book

Solution

Solution

Cocoa’s NSObject base class provides two methods that allocate memory for new instances, +(id)alloc and +(id)allocWithZone:(NSZone *)aZone. These methods are inherited by other Cocoa classes and are seldom overridden. The +alloc method is implemented to call the +allocWithZone: method specifying a default zone argument. Zones are briefly explained in the next section of this chapter. The +alloc and +allocWithZone: methods each return a pointer to a newly allocated block of memory large enough to store an instance of the class that executed the method. The allocated memory contains zeros except for the one instance variable, isa, that all Objective-C objects are required to have. The isa variable is automatically initialized to point to the class object that allocated the memory and is the tie-in to the Objective-C language runtime that enables the instance to receive messages such as -init that are used to complete initialization.

Zones

Memory zones are a feature of Cocoa intended to improve application performance by keeping the memory for objects that are used together close together in the computer’s address space. To explain how the location of objects in memory affects performance, it’s necessary to explain what happens when an application needs more memory than the amount of physical memory available.

Each Cocoa application has a very large amount of addressable memory. When an application dynamically allocates memory, the operating system provides memory even if all available physical memory in the computer is already being used. To accommodate the allocation request, the operating system copies the contents of some physical memory to the hard disk in an operation called paging or swapping. The physical memory that formerly contained the data written to disk is then made available to the application that needed more.

When memory that was copied to disk is needed again, the operating system copies a different area of physical memory to the disk and pages the old memory back into memory. The operating system is able to map the address space of each application to the physical memory even when memory is paged to the disk and back. This feature of the operating system is called virtual memory.

Using virtual memory affects performance because copying the contents of physical memory to and from the hard disk is time-consuming. Too much paging degrades system performance and is called thrashing. The location of memory allocated for object instances is important because if two or more objects that are used together are stored far apart in memory, the likelihood of thrashing increases.

Consider the following scenario: As the memory for one object is needed, it is paged into physical memory from the hard disk. That object then needs to access another object that is still not in physical memory, and even more memory needs be paged in. In the worst case, memory paged in for the second object forces memory for the first object to be paged out again. As the objects that reference each other interact, thrashing results.

Zones are used to make sure the memory allocated for objects that are used together is close together. When one of the objects is needed, the other is almost certainly also needed. Because the objects are in the same zone, the chances are good that all the needed objects are paged into memory at the same time, and when the objects are not needed, they are paged out together as well. Cocoa’s NSZone type specifies a C structure that identifies a memory zone. The +allocWithZone: method accepts an NSZone argument and ­allocates memory from the specified zone. Cocoa provides functions such as NSDefaultMallocZone(), NSCreateZone(), and NSRecycleZone() for managing memory zones. These functions are documented at /Developer/Documentation/Cocoa/ Reference/Foundation/ObjC_classic/Functions/FoundationFunctions.html and online at http://developer.apple.com/.

Initializing Allocated Memory

Once memory for a new instance is allocated, the memory is initialized by calling an instance method. Such instance methods are called initializers and by convention, begin with the word init, and return an id. Some of the advantages of using the id type are described in Chapter 7, “Anonymous Type and Heterogeneous Containers.” Allocation and initialization are almost always combined in one line of code with the following pattern: [[SomeClass alloc] init].

Classes can provide any number of initializers, and the different initializers can each accept different arguments. When multiple initializers are provided, one is usually the Designated Initializer. The Designated Initializer for the NSObject class is –(id)init, and the Designated Initializer for the NSView class is –(id)initWithFrame:(NSRect)aFrame. Any of the provided initializers can be the Designated Initializer, but it must be clearly documented. The Designated Initializer is usually the one that accepts the most arguments. All other initializers call the Designated Initializer in their implementations.

In addition to the Designated Initializer, most Cocoa classes provide an –(id)initWithCoder:(NSCoder *)aCoder method. The significance of -initWithCoder: is explained in Chapter 11, “Archiving and Unarchiving.”

Implementing the Designated Initializer

The Designated Initializer for each class must call the Designated Initializer of its superclass. The following simple MYCircle class is a subclass of NSObject:

@interface MYCircle : NSObject
{
 NSPoint     center;
 float      radius;
}

// Designated Initializer
- (id)initWithCenter:(NSPoint)aPoint radius:(float)aRadius;

@end

@implementation MYCircle

// Designated Initializer
- (id)initWithCenter:(NSPoint)aPoint radius:(float)aRadius
{
 self = [super init];

 if(nil != self)
 {
  center = aPoint;
  radius = aRadius;
 }

 return self;
}

@end

The -(id)initWithCenter:(NSPoint)aPoint radius:(float)aRadius method first assigns the implicit self local variable to the result of calling the superclass’s Designated Initializer. This step is crucial because initializers sometimes return a different object than the one that received the message. This can happen when it is not possible to initialize the receiver correctly for some reason or when a pre-existing instance is returned to avoid the need to initialize a new one.

After the self variable is set, an if statement is used so that instance variables are only initialized if self isn’t nil. This is important because if self is nil, accessing the memory for the instance variables may be an error. This degree of defensive programming is usually unnecessary because few classes ever return nil from their initializers, but nil is a valid return value, so getting in the habit of checking for this case will prevent the occasional problem.

Finally, the -initWithCenter:radius: method returns self. This is the most common pattern for initializers.

Each class that introduces a new Designated Initializer must also override the inherited Designated Initializer to call the new one. Because the MYCircle class introduces -initWithCenter:radius:, it must also implement -init to call -initWithCenter:radius: as follows:

// Overriden inherited Designated Initializer
- (id)init
{
 static const float MYDefaultRadius = 1.0f;

 // call Designated Initializer with default arguments
 return [self initWithCenter:NSZeroPoint radius:MYDefaultRadius];
}

If you adhere to the following guidelines, calling any initializer implemented or inherited by a class will result in a correctly initialized instance:

  • Make sure that the Designated Initializer calls its super class’ implementation of the super class’ Designated Initializer.
  • Assign self to the object returned by the superclass’ Designated Initializer.
  • Do not access instance variables if nil is returned by the superclass’ Designated ­Initializer.
  • Make sure that the superclass’ Designated Initializer is overridden to call the new Designated Initializer.
  • When subclassing, make sure every new initializer that isn’t the Designated Initializer calls the Designated Initializer.

These guidelines greatly simplify the task of creating subclasses. If the guidelines aren’t followed and some initializers fail to call the Designated Initializer, the only way a subclass can be implemented to assure correct initialization of instances is to override every inherited initializer.

Using Zones in Initializers

When using memory zones in your own code, it’s important to allocate memory used by instance variables from the same zone as the object that owns the instance variables. Storing references to memory outside of an object’s zone defeats the whole purpose of zones.

The zone used to allocate an object is determined by sending the -zone message to the object. The MYCircle class can be rewritten so that each instance stores an NSString label allocated from the same zone as the instance itself.

@interface MYCircle : NSObject
{
 NSPoint     center;
 float      radius;
 NSString    *label;
}

// Designated Initializer
- (id)initWithCenter:(NSPoint)aPoint radius:(float)aRadius;

@end

@implementation MYCircle

// Designated Initializer
- (id)initWithCenter:(NSPoint)aPoint radius:(float)aRadius
{
 self = [super init];

 if(nil != self)
 {
  center = aPoint;
  radius = aRadius;
  label = [[NSString allocFromZone:[self zone]]
     initWithString:@”default”];
 }

 return self;
}

// Overriden inherited Designated Initializer
- (id)init
{
 // call Designated Initializer with default arguments
 return [self initWithCenter:NSZeroPoint radius:1.0f];
}

@end

Objects aren’t the only things that can be allocated from zones. The NSZoneMalloc(), NSZoneCalloc(), and NSZoneFree() functions documented in /Developer/Documentation/ Cocoa/Reference/Foundation/ObjC_classic/Functions/FoundationFunctions.html are used to allocate and free blocks of arbitrary memory from specified zones. In Objective-C 2.0 introduced with Mac OS X 10.5, automatic garbage collection automatically frees memory that is allocated using void *__strong NSAllocateCollectable(NSUInteger size, NSUInteger options). For backward compatibility, calling NSAllocateCollectable() with the NSCollectorDisabledOption option has the same behavior as calling NSZoneMalloc().

Objects can also be copied and unarchived using specified zones. The –(id)copyWithZone:(NSZone *)aZone and –(id)mutableCopyWithZone::(NSZone *)aZone methods are explained in Chapter 12, “Copying.” The NSUnarchiver class provides the - (void)setObjectZone:(NSZone *)aZone method used to specify the zone in which unarchived objects are allocated. Archiving and Unarchiving are explained in Chapter 11.

Whenever objects are allocated, they must eventually be deallocated. Cocoa’s reference counted memory management system helps to ensure this is the case. It is described in Chapter 10, “Accessors,” which explains how to manage the memory used by objects. More information about Cocoa’s reference counted memory management is available at /Developer/Documentation/Cocoa/ObjectiveC/4objc_runtime_overview/ Object_Ownership.html.

In Mac OS X 10.5 and later, you can optionally use automatic garbage collection instead of reference counted memory management. However, because automatic garbage collection is optional in Cocoa, it’s necessary to correctly implement reference counted memory management in any new classes you create for the foreseeable future unless you require that the users of your class also use automatic garbage collection.

Regardless of whether zones are used, when an object is deallocated, its –(void)dealloc method is called. Don’t call -dealloc yourself. It’s called automatically when appropriate. The -dealloc method for MYCircle is implemented as follows to make sure the label instance variable allocated in the Designated Initializer is correctly handled:

- (void)dealloc
{
 [label release];

 [super dealloc];
}

If automatic garbage collection is used, the - (void)finalize method is automatically called instead of the –dealloc method. The MYCircle example doesn’t need to implement -finalize because the automatic garbage collector, if used, automatically collects the memory for the label string. MYCircle doesn’t require any special action when its memory is collected. However, it would be necessary to implement the –finalize method if MYCircle had allocated any noncollectible memory via NSAllocateCollectable() with the NSCollectorDisabledOption or needed to perform other end-of-life operations like closing open files.

Creating Temporary Instances

Many Cocoa classes provide methods that combine the two stages of allocating and initializing to return temporary instances. Such methods are called convenience methods. Convenience methods include the name of the class in the method’s name. For example, the NSString class provides the +(id)stringWithString:(NSString *)aString convenience method that’s similar to the -(id)initWithString:(NSString *)aString initializer method used by the MYCircle class. When not using automatic garbage collection, the primary difference between calling [[NSString alloc] initWithString:@”some string”] and [NSString stringWithString:@”some string”] is that +stringWithString: returns an instance that will be automatically deallocated unless you send it a -retain message to prevent deallocation. When using automatic garbage collection, there is no significant difference between the two techniques for obtaining a new instance.

Methods like +stringWithString: are usually implemented as follows:

+ (id)stringWithString:(NSString *)aString
{
 return [[[self alloc] initWithString:aString] autorelease];
}

The implications of the -retain message and the -autorelease message are explained in Chapter 10.

The convenience methods for obtaining instances are almost always paired with similarly named initializers. Besides just reducing the amount of code programmers must write to create and initialize instances, the convenience methods also enable certain optimizations and are used with other patterns. In particular, convenience methods are used in the implementation of the Singleton and Class Clusters patterns in Chapter 13, “Singleton,” and Chapter 25, “Class Clusters,” respectively. Sometimes convenience methods return Flyweight objects, which are described in Chapter 22, “Flyweight” One drawback to using the convenience methods is that you give up flexibility in the way instances are allocated because the allocation technique is hard-coded in the method.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020