Book Image

Objective C Memory Management Essentials

Book Image

Objective C Memory Management Essentials

Overview of this book

Table of Contents (18 chapters)
Objective-C Memory Management Essentials
Credits
About the Authors
About the Reviewers
www.PacktPub.com
Preface
Index

What is an object within Objective-C?


How do things work inside Objective-C? NSObject is the root class of most Objective-C class hierarchies, through it an object inherits basic methods and behaves like an Objective-C object.

This object is an instance of a class and can also be a member of a class or one of its derivatives. So, let's take a deeper look at NSObject. In the early stage, Objective-C had a class called Object. This had a method called +new, which wrapped malloc(), and a method called -free. Since Objective-C objects were generally aliased and managing object life cycles became quite complex, this was troublesome.

NSObject is used by NeXT—Steve Job's second company, founded after he was fired from Apple in 1985—in order to provide reference counting, thus, dividing Object pointers in two categories: pointers that own references and pointers that do not own references. Those pointers that contribute towards the object's reference count are owning reference pointers. If there is a certainty that a reference is going to be held somewhere else for the duration of a variable's lifetime, a non-owning reference pointer can be used avoiding the additional overhead of reference count manipulation since a non-owning reference pointer does not have the added cost of keeping track of object ownership.

Non-owning reference pointers are often used for autoreleased values. Autorelease pools make it possible for a temporary object to receive a non-owning reference pointer in return. An object, by receiving an -autorelease message is added to a list that will be deallocated afterwards, with the destruction of the current autorelease pool. You can call autorelease using the autorelease method as shown here:

 [myObject autorelease];

The following table shows some description on the roles of autorelease and release:

Release type

Description

The autorelease method

An object is sent a release message, but put in an autorelease pool and the object is released when the pool is drained later during the run loop, but still occupies memory

The release method

An object is released immediately and memory is freed after the object is released

Any object that receives the autorelease message will be released when the autorelease pool is drained. Using autorelease instead of the normal release method will extend the lifetime of an object until the pool is drained at the end of the run loop.

At Worldwide Developers Conference (WWDC) 2011, Apple introduced ARC, the acronym of Automatic Reference Counting. It forces the compiler to handle the memory management calls at compile time instead of the conventional garbage collection functionality, which occurs during runtime. ARC also adds some things to the language model in general. It has been supported since iOS5, OS X 10.7, and by GNUstep.

First, what we will find out is that there are two NSObjects in Cocoa, a class and a protocol. Why is this so and what is the purpose of this? Let's look into classes and protocols.

In Objective-C, protocols define a set of behaviors that an object is expected to conform to in certain situations at runtime. For example, a table view object is expected to be able to communicate with a certain data source so that the table view will know what data and information to display. Protocols and classes do not share the same namespaces (a set of identifiers containing names, the names of classes and protocols, thus the same name can exist in different namespaces). It's possible to have both, which are unrelated at the language level, but have the same name. This is the case with NSObject.

If you look at the language, there are no places where you can use either a protocol or a class name. Using class names as the target of message sends, as type names, and in @interface declarations is allowed. Likewise, it's possible to use protocols names in a few identical places; however, not in the same way. Having a protocol with the same name as a class won't result any issue.

It is impossible for root class to have a superclass as they are at the top of the hierarchy, so there is no superclass above a root class and NSObject class is one of them. And I give emphasis on saying one of them because in comparison to other programming languages in Objective-C, it's perfectly possible to have the existence of multiple root classes.

Java's single root class is named java.lang.Object, which is the parent ultimate class of any other. For this reason, any piece of code in Java, which comes from any object, has the basic methods added by java.lang.Object.

Cocoa can have multiple root classes. Besides NSObject, there is NSProxy and a few others root classes; and such root classes are, in part, the reason for the existence of the NSObject protocol. The NSObject protocol determines a specific set of basic methods, expecting their implementation by the others root classes, consequently, making those methods available whenever and wherever they are needed.

The NSObject class is in accordance to the NSObject protocol, which results in the implementation of this basic method:

   //for NSObject class 
  @interface NSObject <NSObject>

Implementing the same method works for NSProxy, which is also in accordance to the NSObject protocol:

   // for NSProxy class @interface NSProxy <NSObject>

Methods such as hash, description, isEqual, isKindOfClass, isProxy, and others are found in the NSObject protocol. NSProxy to NSObject protocol denotes that, implementing the basic NSObject methods, it's still possible to count on NSProxy instances.

Subclassing NSObject would pull in a lot of baggage that may cause a problem. NSProxy assists in order to prevent this by giving you a simpler superclass that doesn't have so much extra stuff in it.

The fact that the NSObject protocol is useful for root classes isn't all that interesting for most Objective-C programming, for the simple fact that we don't make use of other root classes frequently. However, it will be very convenient when you need to make your own protocols.

Let's say, you have the following protocol:

    @protocol MyOwnProtocol
    - (void)myFunction;
    @end

And there is a pointer to a simple object, myOwnObject, that accords to it:

    id<MyProtocol> myOwnObject;

You can tell this object to perform myFunction:

    [myOwnObject myFunction];

However, you cannot ask the object for its description:

    [myOwnObject description]; // no such method in the protocol

And you can't check it for equality:

    [myOwnObject isEqual: anotherObject];
    // no such method in the protocol

In general, you can't ask it to do any of the stuff that a normal object can do. There are times when this doesn't have any importance, but in some circumstances, you will wish to be able to perform this task.

As mentioned earlier, NSObject, the root class of most Objective-C class hierarchies and through NSObjects, your Objective-C classes can inherit an interface to the system and also gain the ability to behave as Objective-C objects. So, NSObject is important if you want your objects to gain access to methods such as isEqual, so on, and so forth. This is where the NSObject protocol comes into the picture. Protocols can inherit from other protocols, which means that MyProtocol can inherit from the NSObject protocol:

    @protocol MyOwnProtocol <NSObject>
    - (void)myFunction;
    @end

This says that not only do objects that conform to MyOwnProtocol respond to myFunction, but they also respond to all those common messages in the NSObject protocol. Knowing that any object in your application directly or indirectly inherits from the NSObject class, that it's in accordance to the NSObject protocol, there is no imposition to any additional requirements on people implementing MyOwnProtocol, while giving you the permission to use these basic methods on instances.

Note

The fact that there are two different NSObjects is abnormal for the frameworks; however, it starts to make sense when you go deeper into it. The NSObject protocol grants the permission to all root classes that have the same basic methods, making, also, a very easy way to declare a protocol that also includes basic functionality expected from any object. The NSObject class introduces it all together, since it's in accordance to the NSObject protocol. One thing to note here is that a custom class that's created and does not inherit NSObject can be considered as a root class, but once you make your custom class inherit from NSObject, then the root class won't be your custom class anymore, and the root class will be NSObject. However, generally, most of your custom classes should inherit from NSObjects; it will implement NSObject's functionality such as alloc, init, release, and so on and without inheriting from NSObject, these functionalities need to be written and implemented by you.