16
Subclassing UITableViewCell

A UITableView displays a list of UITableViewCells. For many applications, the basic cell with its textLabel, detailTextLabel, and imageView is sufficient. However, when you need a cell with more detail or a different layout, you subclass UITableViewCell.

In this chapter, you will create a custom subclass of UITableViewCell to display Possession instances more eloquently. Each of these cells will show a Possession’s name, its value in dollars, and a thumbnail of its image (Figure 16.1).

Figure 16.1  Homepwner with subclassed UITableViewCells

Homepwner with subclassed UITableViewCells

Open Homepwner.xcodeproj. Create a new NSObject subclass and name it HomepwnerItemCell. In HomepwnerItemCell.h, change the superclass to UITableViewCell and import the header file from UIKit.

#​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​ ​<​U​I​K​i​t​/​U​I​K​i​t​.​h​>​

@​i​n​t​e​r​f​a​c​e​ ​H​o​m​e​p​w​n​e​r​I​t​e​m​C​e​l​l​ ​:​ ​U​I​T​a​b​l​e​V​i​e​w​C​e​l​l​

Creating HomepwnerItemCell

UITableViewCell is a UIView subclass. When subclassing UIView (or any of its subclasses), you typically override its drawRect: method to customize the view’s appearance. However, when subclassing UITableViewCell, you don’t change the cell’s appearance directly. Each cell has a subview named contentView, which is a container for the view objects that make up the layout of a cell subclass (Figure 16.2). You subclass UITableViewCell by changing the view objects in a cell’s contentView. For instance, you could create instances of the classes UITextField, UILabel, and UIButton and add them to the contentView. (If you wanted something even more daring, you could create a UIView subclass, override its drawRect:, and add an instance of it to the contentView.)

Figure 16.2  HomepwnerItemCell hierarchy

HomepwnerItemCell hierarchy

Adding subviews to the contentView instead of directly to the UITableViewCell subclass is important because the cell will resize the contentView at certain times. For example, when a table view enters editing mode, the contentView redraws itself to make room for the editing controls (Figure 16.3). If you were to add subviews directly to the UITableViewCell, these editing controls would obscure the subviews. The cell doesn’t know to adjust its size when entering edit mode, but the contentView does.

Figure 16.3  Table view cell layout in standard and editing mode

Table view cell layout in standard and editing mode

Creating subviews

In your cell subclass, you need an instance variable for each subview so that you can set its content as it is displayed in a table view. In HomepwnerItemCell.h, create instance variables for the necessary subviews.

#​i​m​p​o​r​t​ ​<​U​I​K​i​t​/​U​I​K​i​t​.​h​>​

@​i​n​t​e​r​f​a​c​e​ ​H​o​m​e​p​w​n​e​r​I​t​e​m​C​e​l​l​ ​:​ ​U​I​T​a​b​l​e​V​i​e​w​C​e​l​l​
{​
 ​ ​ ​ ​U​I​L​a​b​e​l​ ​*​v​a​l​u​e​L​a​b​e​l​;​
 ​ ​ ​ ​U​I​L​a​b​e​l​ ​*​n​a​m​e​L​a​b​e​l​;​
 ​ ​ ​ ​U​I​I​m​a​g​e​V​i​e​w​ ​*​i​m​a​g​e​V​i​e​w​;​
}​
@​e​n​d​

When an instance of HomepwnerItemCell is created, it will instantiate its valueLabel, nameLabel, and imageView. Then, these subviews will be added to the cell’s contentView. Override the designated initializer in HomepwnerItemCell.m to do this. HomepwnerItemCell.m should now look like this:

#​i​m​p​o​r​t​ ​"​H​o​m​e​p​w​n​e​r​I​t​e​m​C​e​l​l​.​h​"​

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

@​i​m​p​l​e​m​e​n​t​a​t​i​o​n​ ​H​o​m​e​p​w​n​e​r​I​t​e​m​C​e​l​l​
-​ ​(​i​d​)​i​n​i​t​W​i​t​h​S​t​y​l​e​:​(​U​I​T​a​b​l​e​V​i​e​w​C​e​l​l​S​t​y​l​e​)​s​t​y​l​e​
 ​ ​ ​ ​r​e​u​s​e​I​d​e​n​t​i​f​i​e​r​:​(​N​S​S​t​r​i​n​g​ ​*​)​r​e​u​s​e​I​d​e​n​t​i​f​i​e​r​
{​
 ​ ​ ​ ​s​e​l​f​ ​=​ ​[​s​u​p​e​r​ ​i​n​i​t​W​i​t​h​S​t​y​l​e​:​s​t​y​l​e​ ​r​e​u​s​e​I​d​e​n​t​i​f​i​e​r​:​r​e​u​s​e​I​d​e​n​t​i​f​i​e​r​]​;​

 ​ ​ ​ ​i​f​ ​(​s​e​l​f​)​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​a​ ​s​u​b​v​i​e​w​ ​-​ ​d​o​n​'​t​ ​n​e​e​d​ ​t​o​ ​s​p​e​c​i​f​y​ ​i​t​s​ ​p​o​s​i​t​i​o​n​/​s​i​z​e​
 ​ ​ ​ ​ ​ ​ ​ ​v​a​l​u​e​L​a​b​e​l​ ​=​ ​[​[​U​I​L​a​b​e​l​ ​a​l​l​o​c​]​ ​i​n​i​t​W​i​t​h​F​r​a​m​e​:​C​G​R​e​c​t​Z​e​r​o​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​P​u​t​ ​i​t​ ​o​n​ ​t​h​e​ ​c​o​n​t​e​n​t​ ​v​i​e​w​ ​o​f​ ​t​h​e​ ​c​e​l​l​
 ​ ​ ​ ​ ​ ​ ​ ​[​[​s​e​l​f​ ​c​o​n​t​e​n​t​V​i​e​w​]​ ​a​d​d​S​u​b​v​i​e​w​:​v​a​l​u​e​L​a​b​e​l​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​I​t​ ​i​s​ ​b​e​i​n​g​ ​r​e​t​a​i​n​e​d​ ​b​y​ ​i​t​s​ ​s​u​p​e​r​v​i​e​w​
 ​ ​ ​ ​ ​ ​ ​ ​[​v​a​l​u​e​L​a​b​e​l​ ​r​e​l​e​a​s​e​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​S​a​m​e​ ​t​h​i​n​g​ ​w​i​t​h​ ​t​h​e​ ​n​a​m​e​
 ​ ​ ​ ​ ​ ​ ​ ​n​a​m​e​L​a​b​e​l​ ​=​ ​[​[​U​I​L​a​b​e​l​ ​a​l​l​o​c​]​ ​i​n​i​t​W​i​t​h​F​r​a​m​e​:​C​G​R​e​c​t​Z​e​r​o​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​[​[​s​e​l​f​ ​c​o​n​t​e​n​t​V​i​e​w​]​ ​a​d​d​S​u​b​v​i​e​w​:​n​a​m​e​L​a​b​e​l​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​[​n​a​m​e​L​a​b​e​l​ ​r​e​l​e​a​s​e​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​S​a​m​e​ ​t​h​i​n​g​ ​w​i​t​h​ ​t​h​e​ ​i​m​a​g​e​ ​v​i​e​w​
 ​ ​ ​ ​ ​ ​ ​ ​i​m​a​g​e​V​i​e​w​ ​=​ ​[​[​U​I​I​m​a​g​e​V​i​e​w​ ​a​l​l​o​c​]​ ​i​n​i​t​W​i​t​h​F​r​a​m​e​:​C​G​R​e​c​t​Z​e​r​o​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​[​[​s​e​l​f​ ​c​o​n​t​e​n​t​V​i​e​w​]​ ​a​d​d​S​u​b​v​i​e​w​:​i​m​a​g​e​V​i​e​w​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​T​e​l​l​ ​t​h​e​ ​i​m​a​g​e​v​i​e​w​ ​t​o​ ​c​e​n​t​e​r​ ​i​t​s​ ​i​m​a​g​e​ ​i​n​s​i​d​e​ ​i​t​s​ ​f​r​a​m​e​
 ​ ​ ​ ​ ​ ​ ​ ​[​i​m​a​g​e​V​i​e​w​ ​s​e​t​C​o​n​t​e​n​t​M​o​d​e​:​U​I​V​i​e​w​C​o​n​t​e​n​t​M​o​d​e​C​e​n​t​e​r​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​[​i​m​a​g​e​V​i​e​w​ ​r​e​l​e​a​s​e​]​;​
 ​ ​ ​ ​}​

 ​ ​ ​ ​r​e​t​u​r​n​ ​s​e​l​f​;​
}​
@​e​n​d​

Laying out subviews

When a table view’s data source is asked for a cell, it creates a cell, configures its content, and returns it to the table view. The table view then adds the cell as a subview of itself and positions and sizes the cell. Therefore, when you first create a cell, it doesn’t know its size quite yet. For this reason, you do not set the frames of a cell’s content view at initialization time. Instead, you wait until the cell knows how big it is.

When a view changes size, it is sent the message layoutSubviews. Because UITableViewCell (and therefore HomepwnerItemCell) is a subclass of UIView, it also is sent layoutSubviews when its size changes.

In HomepwnerItemCell.m, override layoutSubviews to give each of the subviews a frame. (If you have a hard time picturing the sizes of frame rectangles in your head, draw them out on a piece of paper first.)

-​ ​(​v​o​i​d​)​l​a​y​o​u​t​S​u​b​v​i​e​w​s​
{​
 ​ ​ ​ ​/​/​ ​W​e​ ​a​l​w​a​y​s​ ​c​a​l​l​ ​t​h​i​s​,​ ​t​h​e​ ​t​a​b​l​e​ ​v​i​e​w​ ​c​e​l​l​ ​n​e​e​d​s​ ​t​o​ ​d​o​ ​i​t​s​ ​o​w​n​ ​w​o​r​k​ ​f​i​r​s​t​
 ​ ​ ​ ​[​s​u​p​e​r​ ​l​a​y​o​u​t​S​u​b​v​i​e​w​s​]​;​

 ​ ​ ​ ​/​/​ ​W​e​'​l​l​ ​u​s​e​ ​t​h​i​s​ ​t​o​ ​a​d​d​ ​s​p​a​c​i​n​g​ ​b​e​t​w​e​e​n​ ​b​o​r​d​e​r​s​
 ​ ​ ​ ​f​l​o​a​t​ ​i​n​s​e​t​ ​=​ ​5​.​0​;​

 ​ ​ ​ ​/​/​ ​H​o​w​ ​m​u​c​h​ ​s​p​a​c​e​ ​d​o​ ​w​e​ ​h​a​v​e​ ​t​o​ ​w​o​r​k​ ​w​i​t​h​?​
 ​ ​ ​ ​C​G​R​e​c​t​ ​b​o​u​n​d​s​ ​=​ ​[​[​s​e​l​f​ ​c​o​n​t​e​n​t​V​i​e​w​]​ ​b​o​u​n​d​s​]​;​

 ​ ​ ​ ​/​/​ ​L​e​t​'​s​ ​p​u​l​l​ ​o​u​t​ ​o​f​ ​t​h​e​ ​h​e​i​g​h​t​ ​a​n​d​ ​w​i​d​t​h​
 ​ ​ ​ ​/​/​ ​i​n​t​o​ ​e​a​s​i​e​r​-​t​o​-​t​y​p​e​ ​v​a​r​i​a​b​l​e​ ​n​a​m​e​s​
 ​ ​ ​ ​f​l​o​a​t​ ​h​ ​=​ ​b​o​u​n​d​s​.​s​i​z​e​.​h​e​i​g​h​t​;​
 ​ ​ ​ ​f​l​o​a​t​ ​w​ ​=​ ​b​o​u​n​d​s​.​s​i​z​e​.​w​i​d​t​h​;​

 ​ ​ ​ ​/​/​ ​T​h​i​s​ ​w​i​l​l​ ​b​e​ ​a​ ​c​o​n​s​t​a​n​t​ ​v​a​l​u​e​ ​f​o​r​ ​t​h​e​ ​v​a​l​u​e​F​i​e​l​d​'​s​ ​w​i​d​t​h​
 ​ ​ ​ ​f​l​o​a​t​ ​v​a​l​u​e​W​i​d​t​h​ ​=​ ​4​0​.​0​;​

 ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​a​ ​r​e​c​t​a​n​g​l​e​ ​o​n​ ​t​h​e​ ​l​e​f​t​ ​h​a​n​d​ ​s​i​d​e​ ​o​f​ ​t​h​e​ ​c​e​l​l​ ​f​o​r​ ​t​h​e​ ​i​m​a​g​e​V​i​e​w​
 ​ ​ ​ ​C​G​R​e​c​t​ ​i​m​a​g​e​F​r​a​m​e​ ​=​ ​C​G​R​e​c​t​M​a​k​e​(​i​n​s​e​t​,​ ​i​n​s​e​t​,​ ​4​0​,​ ​4​0​)​;​
 ​ ​ ​ ​[​i​m​a​g​e​V​i​e​w​ ​s​e​t​F​r​a​m​e​:​i​m​a​g​e​F​r​a​m​e​]​;​

 ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​a​ ​r​e​c​t​a​n​g​l​e​ ​i​n​ ​t​h​e​ ​m​i​d​d​l​e​ ​f​o​r​ ​t​h​e​ ​n​a​m​e​
 ​ ​ ​ ​C​G​R​e​c​t​ ​n​a​m​e​F​r​a​m​e​ ​=​ ​C​G​R​e​c​t​M​a​k​e​(​i​m​a​g​e​F​r​a​m​e​.​s​i​z​e​.​w​i​d​t​h​ ​+​ ​i​m​a​g​e​F​r​a​m​e​.​o​r​i​g​i​n​.​x​ ​+​ ​i​n​s​e​t​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​i​n​s​e​t​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​w​ ​-​ ​(​h​ ​+​ ​v​a​l​u​e​W​i​d​t​h​ ​+​ ​i​n​s​e​t​ ​*​ ​4​.​0​)​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​h​ ​-​ ​i​n​s​e​t​ ​*​ ​2​.​0​)​;​
 ​ ​ ​ ​[​n​a​m​e​L​a​b​e​l​ ​s​e​t​F​r​a​m​e​:​n​a​m​e​F​r​a​m​e​]​;​

 ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​a​ ​r​e​c​t​a​n​g​l​e​ ​o​n​ ​t​h​e​ ​r​i​g​h​t​ ​s​i​d​e​ ​o​f​ ​t​h​e​ ​c​e​l​l​ ​f​o​r​ ​t​h​e​ ​v​a​l​u​e​
 ​ ​ ​ ​C​G​R​e​c​t​ ​v​a​l​u​e​F​r​a​m​e​ ​=​ ​C​G​R​e​c​t​M​a​k​e​(​n​a​m​e​F​r​a​m​e​.​s​i​z​e​.​w​i​d​t​h​ ​+​ ​n​a​m​e​F​r​a​m​e​.​o​r​i​g​i​n​.​x​ ​+​ ​i​n​s​e​t​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​i​n​s​e​t​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​v​a​l​u​e​W​i​d​t​h​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​h​ ​-​ ​i​n​s​e​t​ ​*​ ​2​.​0​)​;​
 ​ ​ ​ ​[​v​a​l​u​e​L​a​b​e​l​ ​s​e​t​F​r​a​m​e​:​v​a​l​u​e​F​r​a​m​e​]​;​
}​

This method is fairly ugly, but let’s look at it more closely. First, you always invoke the superclass’ implementation of layoutSubviews. Invoking this method allows the UITableViewCell to layout its subview, the contentView. Then, you get the bounds of the contentView to find out how much area you have to work with when sizing and positioning all of the subviews. (If you don’t invoke the superclass’ implementation of layoutSubviews, the bounds of the contentView may not be correct.) Finally, you set the frame of each subview relative to the contentView’s bounds. This process ensures that instances of HomepwnerItemCell will have an appropriate layout regardless of the size of the UITableViewCell.

Using the custom cell

Now let’s look at the two options for setting the content of the subviews (imageView, nameLabel, and valueLabel). The first option is to create a property for each subview to use when you set the cell content in tableView:cellForRowAtIndexPath: (like you are currently accessing the textLabel property of each cell). The second option is to pass the cell an instance of Possession and have it fill its own subviews. In this chapter, you will use the second option. Either way is perfectly reasonable; however, in the second option, the HomepwnerItemCell is made specifically to represent a Possession instance, so the code is written in a way that’s easier to follow. (The drawback is that HomepwnerItemCell will only be able to represent Possession instances.)

In HomepwnerItemCell.m, implement the method setPossession: to extract values from a Possession instance and display them in the cell.

-​ ​(​v​o​i​d​)​s​e​t​P​o​s​s​e​s​s​i​o​n​:​(​P​o​s​s​e​s​s​i​o​n​ ​*​)​p​o​s​s​e​s​s​i​o​n​
{​
 ​ ​ ​ ​/​/​ ​U​s​i​n​g​ ​a​ ​P​o​s​s​e​s​s​i​o​n​ ​i​n​s​t​a​n​c​e​,​ ​w​e​ ​c​a​n​ ​s​e​t​ ​t​h​e​ ​v​a​l​u​e​s​ ​o​f​ ​t​h​e​ ​s​u​b​v​i​e​w​s​
 ​ ​ ​ ​[​v​a​l​u​e​L​a​b​e​l​ ​s​e​t​T​e​x​t​:​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​[​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​"​,​ ​[​p​o​s​s​e​s​s​i​o​n​ ​v​a​l​u​e​I​n​D​o​l​l​a​r​s​]​]​]​;​
 ​ ​ ​ ​[​n​a​m​e​L​a​b​e​l​ ​s​e​t​T​e​x​t​:​[​p​o​s​s​e​s​s​i​o​n​ ​p​o​s​s​e​s​s​i​o​n​N​a​m​e​]​]​;​
}​

Note that we’re not setting the imageView yet. We’ll get to that in the next section.

Also, declare setPossession: in HomepwnerItemCell.h:

@​c​l​a​s​s​ ​P​o​s​s​e​s​s​i​o​n​;​

@​i​n​t​e​r​f​a​c​e​ ​H​o​m​e​p​w​n​e​r​I​t​e​m​C​e​l​l​ ​:​ ​U​I​T​a​b​l​e​V​i​e​w​C​e​l​l​
{​
 ​ ​ ​ ​U​I​L​a​b​e​l​ ​*​v​a​l​u​e​L​a​b​e​l​;​
 ​ ​ ​ ​U​I​L​a​b​e​l​ ​*​n​a​m​e​L​a​b​e​l​;​
 ​ ​ ​ ​U​I​I​m​a​g​e​V​i​e​w​ ​*​i​m​a​g​e​V​i​e​w​;​
}​
-​ ​(​v​o​i​d​)​s​e​t​P​o​s​s​e​s​s​i​o​n​:​(​P​o​s​s​e​s​s​i​o​n​ ​*​)​p​o​s​s​e​s​s​i​o​n​;​
@​e​n​d​

You can build the application to make sure there are no compile errors. Running it won’t show anything new because you aren’t yet returning HomepwnerItemCells from the UITableView data source method implemented by ItemsViewController. In ItemsViewController.m, import the header file for HomepwnerItemCell.

#​i​m​p​o​r​t​ ​"​H​o​m​e​p​w​n​e​r​I​t​e​m​C​e​l​l​.​h​"​

@​i​m​p​l​e​m​e​n​t​a​t​i​o​n​ ​I​t​e​m​s​V​i​e​w​C​o​n​t​r​o​l​l​e​r​

In ItemsViewController.m, update the method tableView:cellForRowAtIndexPath: to return instances of your new cell subclass.

-​ ​(​U​I​T​a​b​l​e​V​i​e​w​C​e​l​l​ ​*​)​t​a​b​l​e​V​i​e​w​:​(​U​I​T​a​b​l​e​V​i​e​w​ ​*​)​t​a​b​l​e​V​i​e​w​
 ​ ​ ​ ​ ​ ​ ​ ​ ​c​e​l​l​F​o​r​R​o​w​A​t​I​n​d​e​x​P​a​t​h​:​(​N​S​I​n​d​e​x​P​a​t​h​ ​*​)​i​n​d​e​x​P​a​t​h​
{​
 ​ ​ ​ ​/​/​ ​G​e​t​ ​i​n​s​t​a​n​c​e​ ​o​f​ ​a​ ​H​o​m​e​p​w​n​e​r​I​t​e​m​C​e​l​l​ ​-​ ​e​i​t​h​e​r​ ​a​n​ ​u​n​u​s​e​d​ ​o​n​e​ ​o​r​ ​a​ ​n​e​w​ ​o​n​e​.​
 ​ ​ ​ ​/​/​ ​T​h​e​ ​m​e​t​h​o​d​ ​r​e​t​u​r​n​s​ ​a​ ​U​I​T​a​b​l​e​V​i​e​w​C​e​l​l​;​ ​w​e​ ​t​y​p​e​c​a​s​t​ ​i​t​ ​a​s​ ​a​ ​H​o​m​e​p​w​n​e​r​I​t​e​m​C​e​l​l​.​
 ​ ​ ​ ​H​o​m​e​p​w​n​e​r​I​t​e​m​C​e​l​l​ ​*​c​e​l​l​ ​=​ ​(​H​o​m​e​p​w​n​e​r​I​t​e​m​C​e​l​l​ ​*​)​[​t​a​b​l​e​V​i​e​w​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​d​e​q​u​e​u​e​R​e​u​s​a​b​l​e​C​e​l​l​W​i​t​h​I​d​e​n​t​i​f​i​e​r​:​@​"​H​o​m​e​p​w​n​e​r​I​t​e​m​C​e​l​l​"​]​;​

 ​ ​ ​ ​i​f​ ​(​!​c​e​l​l​)​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​c​e​l​l​ ​=​ ​[​[​[​H​o​m​e​p​w​n​e​r​I​t​e​m​C​e​l​l​ ​a​l​l​o​c​]​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​i​n​i​t​W​i​t​h​S​t​y​l​e​:​U​I​T​a​b​l​e​V​i​e​w​C​e​l​l​S​t​y​l​e​D​e​f​a​u​l​t​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​r​e​u​s​e​I​d​e​n​t​i​f​i​e​r​:​@​"​H​o​m​e​p​w​n​e​r​I​t​e​m​C​e​l​l​"​]​ ​a​u​t​o​r​e​l​e​a​s​e​]​;​
 ​ ​ ​ ​}​

 ​ ​ ​ ​N​S​A​r​r​a​y​ ​*​p​o​s​s​e​s​s​i​o​n​s​ ​=​ ​[​[​P​o​s​s​e​s​s​i​o​n​S​t​o​r​e​ ​d​e​f​a​u​l​t​S​t​o​r​e​]​ ​a​l​l​P​o​s​s​e​s​s​i​o​n​s​]​;​
 ​ ​ ​ ​P​o​s​s​e​s​s​i​o​n​ ​*​p​ ​=​ ​[​p​o​s​s​e​s​s​i​o​n​s​ ​o​b​j​e​c​t​A​t​I​n​d​e​x​:​[​i​n​d​e​x​P​a​t​h​ ​r​o​w​]​]​;​

 ​ ​ ​ ​/​/​ ​I​n​s​t​e​a​d​ ​o​f​ ​s​e​t​t​i​n​g​ ​e​a​c​h​ ​l​a​b​e​l​ ​d​i​r​e​c​t​l​y​,​ ​w​e​ ​p​a​s​s​ ​i​t​ ​a​ ​p​o​s​s​e​s​s​i​o​n​ ​o​b​j​e​c​t​
 ​ ​ ​ ​/​/​ ​i​t​ ​k​n​o​w​s​ ​h​o​w​ ​t​o​ ​c​o​n​f​i​g​u​r​e​ ​i​t​s​ ​o​w​n​ ​s​u​b​v​i​e​w​s​
 ​ ​ ​ ​[​c​e​l​l​ ​s​e​t​P​o​s​s​e​s​s​i​o​n​:​p​]​;​

 ​ ​ ​ ​r​e​t​u​r​n​ ​c​e​l​l​;​
}​

Notice that the dequeueReusableCellWithIdentifier: method returns a UITableViewCell that we typecast as a HomepwnerItemCell because we know that’s what we’re getting back. Remember that typecasting does not change anything about the object; it only helps the compiler know what messages are valid.

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

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