19
Object Instance Variables

Thus far, the instance variables declared in your classes have been simple C types like int or float. It’s far more common for instance variables to be pointers to other objects. An object instance variable points to another object and describes a relationship between the two objects. Usually, object instance variables fall into one of three categories:

  • Object-type attributes: a pointer to a simple, value-like object like an NSString or an NSNumber. For example, an employee’s last name would be stored in an NSString. Thus, an instance of Employee would have an instance variable that would be a pointer to an instance of NSString.

  • To-one relationships: a pointer to a single complex object. For example, an employee might have a spouse. Thus, an instance of Employee would have an instance variable that would be a pointer to an instance of Person.

  • To-many relationships: a pointer to an instance of a collection class, such as an NSMutableArray. (We’ll see other examples of collections in Chapter 21.) For example, an employee might have children. In this case, the instance of Employee would have an instance variable that would be a pointer to an instance of NSMutableArray. The NSMutableArray would hold a list of pointers to one or more Person objects.

(Notice that, in the above list, I refer to an NSString. NSString is the class, but an NSString is shorthand for an NSString instance. This usage is a little confusing but very common, so it’s good to get comfortable with it.)

Figure 19.1  An Employee with object instance variables

An Employee with object instance variables

Notice that, as in other diagrams, pointers are represented by arrows. In addition, those pointers are named. So an Employee would have three new instance variables: lastName, spouse, and children. The declaration of Employee’s instance variables would look like this:

@​i​n​t​e​r​f​a​c​e​ ​E​m​p​l​o​y​e​e​ ​:​ ​P​e​r​s​o​n​
{​
 ​ ​ ​ ​i​n​t​ ​e​m​p​l​o​y​e​e​I​D​;​
 ​ ​ ​ ​N​S​S​t​r​i​n​g​ ​*​l​a​s​t​N​a​m​e​;​
 ​ ​ ​ ​P​e​r​s​o​n​ ​*​s​p​o​u​s​e​;​
 ​ ​ ​ ​N​S​M​u​t​a​b​l​e​A​r​r​a​y​ ​*​c​h​i​l​d​r​e​n​;​
}​

With the exception of employeeID, these variables are all pointers. Object instance variables are always pointers. For example, the variable spouse is a pointer to another object that lives on the heap. The pointer spouse is inside the Employee object, but the Person object it points to is not. Objects don’t live inside other objects. The employee object contains its employee ID (the variable and the value itself), but it only knows where its spouse lives in memory.

There are two important side-effects to objects pointing to rather than containing other objects:

  • One object can take on several roles. For example, it is likely that the employee’s spouse is also listed as the emergency contact for the children:

    Figure 19.2  One object, multiple roles

    One object, multiple roles
  • You end up with a lot of distinct objects using up your program’s memory. You need the objects being used to stay around, but you want the unnecessary ones to be deallocated (have their memory returned to the heap) so that their memory can be reused. Reusing memory keeps your program’s memory footprint as small as possible, which will make your entire computer feel more responsive. On a mobile device (like an iPhone), the operating system will kill your program if its memory footprint gets too big.

Object ownership and ARC

To manage these issues, we have the idea of object ownership. When an object has an object instance variable, the object with the pointer is said to own the object that is being pointed to.

From the other end of things, an object knows how many owners it currently has. For instance, in the diagram above, the instance of Person has three owners: the Employee object and the two Child objects. When an object has zero owners, it figures no one needs it around anymore and deallocates itself.

The owner count of each object is handled by Automatic Reference Counting. ARC is a recent development in Objective-C. Before Xcode 4.2, we managed ownership manually and spent a lot of time and effort doing so. (There’s more about manual reference counting and how it worked in the final section of Chapter 20. All the code in this book, however, assumes that you are using ARC.)

Let’s expand the BMITime project to see how ownership works in practice. It is not uncommon for a company to keep track of what assets have been issued to which employee. We are going to create an Asset class, and each Employee will have an array containing his or her assets.

Figure 19.3  Employees and assets

Employees and assets

This is often called a parent-child relationship: The parent (an instance of Employee) has a collection of children (an NSMutableArray of Asset objects).

Creating the Asset class

Create a new file: an Objective-C subclass of NSObject. Name it Asset. Open Asset.h and declare two instance variables and two properties:

#​i​m​p​o​r​t​ ​<​F​o​u​n​d​a​t​i​o​n​/​F​o​u​n​d​a​t​i​o​n​.​h​>​

@​i​n​t​e​r​f​a​c​e​ ​A​s​s​e​t​ ​:​ ​N​S​O​b​j​e​c​t​
{​
 ​ ​ ​ ​N​S​S​t​r​i​n​g​ ​*​l​a​b​e​l​;​
 ​ ​ ​ ​u​n​s​i​g​n​e​d​ ​i​n​t​ ​r​e​s​a​l​e​V​a​l​u​e​;​
}​
@​p​r​o​p​e​r​t​y​ ​(​s​t​r​o​n​g​)​ ​N​S​S​t​r​i​n​g​ ​*​l​a​b​e​l​;​
@​p​r​o​p​e​r​t​y​ ​u​n​s​i​g​n​e​d​ ​i​n​t​ ​r​e​s​a​l​e​V​a​l​u​e​;​
@​e​n​d​

Notice the strong modifier on the @property declaration for label. That says, This is a pointer to an object upon which I claim ownership. (We’ll talk about other options for this property attribute in Chapter 20.)

Remember that when an object doesn’t have any owners, it is deallocated. When an object is being deallocated, it is sent the message dealloc. (Every object inherits the dealloc method from NSObject.) You are going to override dealloc so that you can see when instances of Asset are being deallocated.

To make it clear which particular instance of Asset is being deallocated, you’ll also implement another NSObject method, description. This method returns a string that is a useful description of an instance of the class. For Asset, you’re going to have description return a string that includes the instance’s label and resaleValue.

Open Asset.m. Synthesize the accessors for your instance variables and then override description and dealloc.

#​i​m​p​o​r​t​ ​"​A​s​s​e​t​.​h​"​

@​i​m​p​l​e​m​e​n​t​a​t​i​o​n​ ​A​s​s​e​t​

@​s​y​n​t​h​e​s​i​z​e​ ​l​a​b​e​l​,​ ​r​e​s​a​l​e​V​a​l​u​e​;​

-​ ​(​N​S​S​t​r​i​n​g​ ​*​)​d​e​s​c​r​i​p​t​i​o​n​
{​
 ​ ​ ​ ​r​e​t​u​r​n​ ​[​N​S​S​t​r​i​n​g​ ​s​t​r​i​n​g​W​i​t​h​F​o​r​m​a​t​:​@​"​<​%​@​:​ ​$​%​d​ ​>​"​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​[​s​e​l​f​ ​l​a​b​e​l​]​,​ ​[​s​e​l​f​ ​r​e​s​a​l​e​V​a​l​u​e​]​]​;​
}​

-​ ​(​v​o​i​d​)​d​e​a​l​l​o​c​
{​
 ​ ​ ​ ​N​S​L​o​g​(​@​"​d​e​a​l​l​o​c​a​t​i​n​g​ ​%​@​"​,​ ​s​e​l​f​)​;​
}​

@​e​n​d​

Notice the %@ token in the format strings in the code above. This token is replaced with the result of sending the description message to the corresponding variable (which must be a pointer to an object so that it can receive this message).

Try building what you have so far to see if you made any errors typing it in. You can build your program without running it by using the keyboard shortcut Command-B. This is useful for testing your code without taking the time to run the program or when you know the program isn’t ready to run yet. Plus, it’s always a good idea to build after making changes so that if you’ve introduced a syntax error, you can find and fix it right away. If you wait, you won’t be as sure what changes are responsible for your new bug.

Adding a to-many relationship to Employee

Now you are going to add a to-many relationship to the Employee class. Recall that a to-many relationship includes a collection object (like an array) and the objects contained in the collection. There are two other important things to know about collections and ownership:

  • When an object is added to the collection, the collection establishes a pointer to the object, and the object gains an owner.

  • When an object is removed from a collection, the collection gets rid of its pointer to the object, and the object loses an owner.

To set up the to-many relationship in Employee, you’ll need a new instance variable to hold a pointer to the mutable array of assets. You’ll also need a couple of methods. Open Employee.h and add them:

#​i​m​p​o​r​t​ ​"​P​e​r​s​o​n​.​h​"​
@​c​l​a​s​s​ ​A​s​s​e​t​;​

@​i​n​t​e​r​f​a​c​e​ ​E​m​p​l​o​y​e​e​ ​:​ ​P​e​r​s​o​n​
{​
 ​ ​ ​ ​i​n​t​ ​e​m​p​l​o​y​e​e​I​D​;​
 ​ ​ ​ ​N​S​M​u​t​a​b​l​e​A​r​r​a​y​ ​*​a​s​s​e​t​s​;​
}​
@​p​r​o​p​e​r​t​y​ ​i​n​t​ ​e​m​p​l​o​y​e​e​I​D​;​
-​ ​(​v​o​i​d​)​a​d​d​A​s​s​e​t​s​O​b​j​e​c​t​:​(​A​s​s​e​t​ ​*​)​a​;​
-​ ​(​u​n​s​i​g​n​e​d​ ​i​n​t​)​v​a​l​u​e​O​f​A​s​s​e​t​s​;​

@​e​n​d​

Notice the line that says @class Asset;. As the compiler is reading this file, it will come across the class name Asset. If it doesn’t know about the class, it will throw an error. The @class Asset; line tells the compiler There is a class called Asset. Don’t panic when you see it in this file. That’s all you need to know for now.

Using @class instead of #import gives the compiler less information, but makes the processing of this particular file faster. You can use @class with Employee.h and other header files because the compiler doesn’t need to know a lot to process a file of declarations.

Now turn your attention to Employee.m. With a to-many relationship, you need to create the collection object (an array, in our case) before you put anything in it. You can do this when the original object (an employee) is first created, or you can be lazy and wait until the collection is needed. Let’s be lazy.

#​i​m​p​o​r​t​ ​"​E​m​p​l​o​y​e​e​.​h​"​
#​i​m​p​o​r​t​ ​"​A​s​s​e​t​.​h​"​

@​i​m​p​l​e​m​e​n​t​a​t​i​o​n​ ​E​m​p​l​o​y​e​e​

@​s​y​n​t​h​e​s​i​z​e​ ​e​m​p​l​o​y​e​e​I​D​;​

-​ ​(​v​o​i​d​)​a​d​d​A​s​s​e​t​s​O​b​j​e​c​t​:​(​A​s​s​e​t​ ​*​)​a​
{​
 ​ ​ ​ ​/​/​ ​I​s​ ​a​s​s​e​t​s​ ​n​i​l​?​
 ​ ​ ​ ​i​f​ ​(​!​a​s​s​e​t​s​)​ ​{​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​t​h​e​ ​a​r​r​a​y​
 ​ ​ ​ ​ ​ ​ ​ ​a​s​s​e​t​s​ ​=​ ​[​[​N​S​M​u​t​a​b​l​e​A​r​r​a​y​ ​a​l​l​o​c​]​ ​i​n​i​t​]​;​
 ​ ​ ​ ​}​
 ​ ​ ​ ​[​a​s​s​e​t​s​ ​a​d​d​O​b​j​e​c​t​:​a​]​;​
}​

-​ ​(​u​n​s​i​g​n​e​d​ ​i​n​t​)​v​a​l​u​e​O​f​A​s​s​e​t​s​
{​
 ​ ​ ​ ​/​/​ ​S​u​m​ ​u​p​ ​t​h​e​ ​r​e​s​a​l​e​ ​v​a​l​u​e​ ​o​f​ ​t​h​e​ ​a​s​s​e​t​s​
 ​ ​ ​ ​u​n​s​i​g​n​e​d​ ​i​n​t​ ​s​u​m​ ​=​ ​0​;​
 ​ ​ ​ ​f​o​r​ ​(​A​s​s​e​t​ ​*​a​ ​i​n​ ​a​s​s​e​t​s​)​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​s​u​m​ ​+​=​ ​[​a​ ​r​e​s​a​l​e​V​a​l​u​e​]​;​
 ​ ​ ​ ​}​
 ​ ​ ​ ​r​e​t​u​r​n​ ​s​u​m​;​
}​

-​ ​(​f​l​o​a​t​)​b​o​d​y​M​a​s​s​I​n​d​e​x​
{​
 ​ ​ ​ ​f​l​o​a​t​ ​n​o​r​m​a​l​B​M​I​ ​=​ ​[​s​u​p​e​r​ ​b​o​d​y​M​a​s​s​I​n​d​e​x​]​;​
 ​ ​ ​ ​r​e​t​u​r​n​ ​n​o​r​m​a​l​B​M​I​ ​*​ ​0​.​9​;​
}​

-​ ​(​N​S​S​t​r​i​n​g​ ​*​)​d​e​s​c​r​i​p​t​i​o​n​
{​
 ​ ​ ​ ​r​e​t​u​r​n​ ​[​N​S​S​t​r​i​n​g​ ​s​t​r​i​n​g​W​i​t​h​F​o​r​m​a​t​:​@​"​<​E​m​p​l​o​y​e​e​ ​%​d​:​ ​$​%​d​ ​i​n​ ​a​s​s​e​t​s​>​"​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​[​s​e​l​f​ ​e​m​p​l​o​y​e​e​I​D​]​,​ ​[​s​e​l​f​ ​v​a​l​u​e​O​f​A​s​s​e​t​s​]​]​;​
}​

-​ ​(​v​o​i​d​)​d​e​a​l​l​o​c​
{​
 ​ ​ ​ ​N​S​L​o​g​(​@​"​d​e​a​l​l​o​c​a​t​i​n​g​ ​%​@​"​,​ ​s​e​l​f​)​;​
}​

@​e​n​d​

To process the Employee.m file, the compiler needs to know a lot about the Asset class. Thus, you imported Asset.h instead of using @class.

Also notice that you overrode description and dealloc to track the deallocation of Employee instances.

Build the project to see if you’ve made any mistakes.

Now you need to create some assets and assign them to employees. Edit main.m:

#​i​m​p​o​r​t​ ​<​F​o​u​n​d​a​t​i​o​n​/​F​o​u​n​d​a​t​i​o​n​.​h​>​
#​i​m​p​o​r​t​ ​"​E​m​p​l​o​y​e​e​.​h​"​
#​i​m​p​o​r​t​ ​"​A​s​s​e​t​.​h​"​

i​n​t​ ​m​a​i​n​(​i​n​t​ ​a​r​g​c​,​ ​c​o​n​s​t​ ​c​h​a​r​ ​*​ ​a​r​g​v​[​]​)​
{​
 ​ ​ ​ ​@​a​u​t​o​r​e​l​e​a​s​e​p​o​o​l​ ​{​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​a​n​ ​a​r​r​a​y​ ​o​f​ ​E​m​p​l​o​y​e​e​ ​o​b​j​e​c​t​s​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​M​u​t​a​b​l​e​A​r​r​a​y​ ​*​e​m​p​l​o​y​e​e​s​ ​=​ ​[​[​N​S​M​u​t​a​b​l​e​A​r​r​a​y​ ​a​l​l​o​c​]​ ​i​n​i​t​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​f​o​r​ ​(​i​n​t​ ​i​ ​=​ ​0​;​ ​i​ ​<​ ​1​0​;​ ​i​+​+​)​ ​{​

 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​a​n​ ​i​n​s​t​a​n​c​e​ ​o​f​ ​E​m​p​l​o​y​e​e​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​E​m​p​l​o​y​e​e​ ​*​p​e​r​s​o​n​ ​=​ ​[​[​E​m​p​l​o​y​e​e​ ​a​l​l​o​c​]​ ​i​n​i​t​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​G​i​v​e​ ​t​h​e​ ​i​n​s​t​a​n​c​e​ ​v​a​r​i​a​b​l​e​s​ ​i​n​t​e​r​e​s​t​i​n​g​ ​v​a​l​u​e​s​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​[​p​e​r​s​o​n​ ​s​e​t​W​e​i​g​h​t​I​n​K​i​l​o​s​:​9​0​ ​+​ ​i​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​[​p​e​r​s​o​n​ ​s​e​t​H​e​i​g​h​t​I​n​M​e​t​e​r​s​:​1​.​8​ ​-​ ​i​/​1​0​.​0​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​[​p​e​r​s​o​n​ ​s​e​t​E​m​p​l​o​y​e​e​I​D​:​i​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​P​u​t​ ​t​h​e​ ​e​m​p​l​o​y​e​e​ ​i​n​ ​t​h​e​ ​e​m​p​l​o​y​e​e​s​ ​a​r​r​a​y​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​[​e​m​p​l​o​y​e​e​s​ ​a​d​d​O​b​j​e​c​t​:​p​e​r​s​o​n​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​}​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​1​0​ ​a​s​s​e​t​s​
 ​ ​ ​ ​ ​ ​ ​ ​f​o​r​ ​(​i​n​t​ ​i​ ​=​ ​0​;​ ​i​ ​<​ ​1​0​;​ ​i​+​+​)​ ​{​

 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​a​n​ ​a​s​s​e​t​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​A​s​s​e​t​ ​*​a​s​s​e​t​ ​=​ ​[​[​A​s​s​e​t​ ​a​l​l​o​c​]​ ​i​n​i​t​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​G​i​v​e​ ​i​t​ ​a​n​ ​i​n​t​e​r​e​s​t​i​n​g​ ​l​a​b​e​l​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​N​S​S​t​r​i​n​g​ ​*​c​u​r​r​e​n​t​L​a​b​e​l​ ​=​ ​[​N​S​S​t​r​i​n​g​ ​s​t​r​i​n​g​W​i​t​h​F​o​r​m​a​t​:​@​"​L​a​p​t​o​p​ ​%​d​"​,​ ​i​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​[​a​s​s​e​t​ ​s​e​t​L​a​b​e​l​:​c​u​r​r​e​n​t​L​a​b​e​l​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​[​a​s​s​e​t​ ​s​e​t​R​e​s​a​l​e​V​a​l​u​e​:​i​ ​*​ ​1​7​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​G​e​t​ ​a​ ​r​a​n​d​o​m​ ​n​u​m​b​e​r​ ​b​e​t​w​e​e​n​ ​0​ ​a​n​d​ ​9​ ​i​n​c​l​u​s​i​v​e​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​N​S​U​I​n​t​e​g​e​r​ ​r​a​n​d​o​m​I​n​d​e​x​ ​=​ ​r​a​n​d​o​m​(​)​ ​%​ ​[​e​m​p​l​o​y​e​e​s​ ​c​o​u​n​t​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​F​i​n​d​ ​t​h​a​t​ ​e​m​p​l​o​y​e​e​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​E​m​p​l​o​y​e​e​ ​*​r​a​n​d​o​m​E​m​p​l​o​y​e​e​ ​=​ ​[​e​m​p​l​o​y​e​e​s​ ​o​b​j​e​c​t​A​t​I​n​d​e​x​:​r​a​n​d​o​m​I​n​d​e​x​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​A​s​s​i​g​n​ ​t​h​e​ ​a​s​s​e​t​ ​t​o​ ​t​h​e​ ​e​m​p​l​o​y​e​e​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​[​r​a​n​d​o​m​E​m​p​l​o​y​e​e​ ​a​d​d​A​s​s​e​t​s​O​b​j​e​c​t​:​a​s​s​e​t​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​}​


 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​E​m​p​l​o​y​e​e​s​:​ ​%​@​"​,​ ​e​m​p​l​o​y​e​e​s​)​;​

 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​G​i​v​i​n​g​ ​u​p​ ​o​w​n​e​r​s​h​i​p​ ​o​f​ ​o​n​e​ ​e​m​p​l​o​y​e​e​"​)​;​

 ​ ​ ​ ​ ​ ​ ​ ​[​e​m​p​l​o​y​e​e​s​ ​r​e​m​o​v​e​O​b​j​e​c​t​A​t​I​n​d​e​x​:​5​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​G​i​v​i​n​g​ ​u​p​ ​o​w​n​e​r​s​h​i​p​ ​o​f​ ​a​r​r​a​y​"​)​;​

 ​ ​ ​ ​ ​ ​ ​ ​e​m​p​l​o​y​e​e​s​ ​=​ ​n​i​l​;​

 ​ ​ ​ ​}​
 ​ ​ ​ ​r​e​t​u​r​n​ ​0​;​
}​

Build and run the program. You should see something like this:

E​m​p​l​o​y​e​e​s​:​ ​(​
 ​ ​ ​ ​"​<​E​m​p​l​o​y​e​e​ ​0​:​ ​$​0​ ​i​n​ ​a​s​s​e​t​s​>​"​,​
 ​ ​ ​ ​"​<​E​m​p​l​o​y​e​e​ ​1​:​ ​$​1​5​3​ ​i​n​ ​a​s​s​e​t​s​>​"​,​
 ​ ​ ​ ​"​<​E​m​p​l​o​y​e​e​ ​2​:​ ​$​1​1​9​ ​i​n​ ​a​s​s​e​t​s​>​"​,​
 ​ ​ ​ ​"​<​E​m​p​l​o​y​e​e​ ​3​:​ ​$​6​8​ ​i​n​ ​a​s​s​e​t​s​>​"​,​
 ​ ​ ​ ​"​<​E​m​p​l​o​y​e​e​ ​4​:​ ​$​0​ ​i​n​ ​a​s​s​e​t​s​>​"​,​
 ​ ​ ​ ​"​<​E​m​p​l​o​y​e​e​ ​5​:​ ​$​1​3​6​ ​i​n​ ​a​s​s​e​t​s​>​"​,​
 ​ ​ ​ ​"​<​E​m​p​l​o​y​e​e​ ​6​:​ ​$​1​1​9​ ​i​n​ ​a​s​s​e​t​s​>​"​,​
 ​ ​ ​ ​"​<​E​m​p​l​o​y​e​e​ ​7​:​ ​$​3​4​ ​i​n​ ​a​s​s​e​t​s​>​"​,​
 ​ ​ ​ ​"​<​E​m​p​l​o​y​e​e​ ​8​:​ ​$​0​ ​i​n​ ​a​s​s​e​t​s​>​"​,​
 ​ ​ ​ ​"​<​E​m​p​l​o​y​e​e​ ​9​:​ ​$​1​3​6​ ​i​n​ ​a​s​s​e​t​s​>​"​
)​
G​i​v​i​n​g​ ​u​p​ ​o​w​n​e​r​s​h​i​p​ ​o​f​ ​o​n​e​ ​e​m​p​l​o​y​e​e​
d​e​a​l​l​o​c​a​t​i​n​g​ ​<​E​m​p​l​o​y​e​e​ ​5​:​ ​$​1​3​6​ ​i​n​ ​a​s​s​e​t​s​>​
d​e​a​l​l​o​c​a​t​i​n​g​ ​<​L​a​p​t​o​p​ ​3​:​ ​$​5​1​ ​>​
d​e​a​l​l​o​c​a​t​i​n​g​ ​<​L​a​p​t​o​p​ ​5​:​ ​$​8​5​ ​ ​>​
G​i​v​i​n​g​ ​u​p​ ​o​w​n​e​r​s​h​i​p​ ​o​f​ ​a​r​r​a​y​
d​e​a​l​l​o​c​a​t​i​n​g​ ​<​E​m​p​l​o​y​e​e​ ​0​:​ ​$​0​ ​i​n​ ​a​s​s​e​t​s​>​
d​e​a​l​l​o​c​a​t​i​n​g​ ​<​E​m​p​l​o​y​e​e​ ​1​:​ ​$​1​5​3​ ​i​n​ ​a​s​s​e​t​s​>​
d​e​a​l​l​o​c​a​t​i​n​g​ ​<​L​a​p​t​o​p​ ​9​:​ ​$​1​5​3​ ​>​
…​
d​e​a​l​l​o​c​a​t​i​n​g​ ​<​E​m​p​l​o​y​e​e​ ​9​:​ ​$​1​3​6​ ​i​n​ ​a​s​s​e​t​s​>​
d​e​a​l​l​o​c​i​n​g​ ​<​L​a​p​t​o​p​ ​8​:​ ​$​1​3​6​ ​>​

When employee #5 is removed from the array, it is deallocated because it has no owner. Then its assets are deallocated because they have no owner. (And you’ll have to trust me on this: the labels (instances of NSString) of the deallocated assets are also deallocated once they have no owner.)

When employees is set to nil, the array no longer has an owner. So it is deallocated, which sets up an even larger chain reaction of memory clean-up and deallocation when, suddenly, none of the employees has an owner.

Tidy, right? As the objects become unnecessary, they are being deallocated. This is good. When unnecessary objects don’t get deallocated, you are said to have a memory leak. Typically a memory leak causes more and more objects to linger unnecessarily over time. The memory footprint of your application just gets bigger and bigger. On iOS, the operating system will eventually kill your application. On Mac OS X, the performance of the entire system will suffer as the machine spends more and more time swapping data out of memory and onto disk.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset