Updating BNRItemCell

Although the row heights adjust based on the preferred text size, the cell content is not adjusting. You will add Dynamic Type support to BNRItemCell shortly. First, pay attention to how the cell subviews adjust appropriately based on the cell height. Because of your thoughtful use of Auto Layout when creating BNRItemCell, the interface adjusts elegantly (Figure 20.5). The imageView stays vertically centered in the cell and pinned to the left, nameLabel is pinned to the top, serialNumberLabel is pinned to the bottom, and valueLabel stays centered and pinned to the right.

Figure 20.5  Auto Layout in action

Auto Layout in action

This worked great while the text was a fixed size, but when you update the class to use Dynamic Type you will need to make some changes. Let’s begin by implementing the Dynamic Type code to update the labels, which will closely follow what you did with BNRDetailViewController and BNRItemsViewController.

Open BNRItemCell.m and make the following changes:

-​ ​(​v​o​i​d​)​u​p​d​a​t​e​I​n​t​e​r​f​a​c​e​F​o​r​D​y​n​a​m​i​c​T​y​p​e​S​i​z​e​
{​
 ​ ​ ​ ​U​I​F​o​n​t​ ​*​f​o​n​t​ ​=​ ​[​U​I​F​o​n​t​ ​p​r​e​f​e​r​r​e​d​F​o​n​t​F​o​r​T​e​x​t​S​t​y​l​e​:​U​I​F​o​n​t​T​e​x​t​S​t​y​l​e​B​o​d​y​]​;​
 ​ ​ ​ ​s​e​l​f​.​n​a​m​e​L​a​b​e​l​.​f​o​n​t​ ​=​ ​f​o​n​t​;​
 ​ ​ ​ ​s​e​l​f​.​s​e​r​i​a​l​N​u​m​b​e​r​L​a​b​e​l​.​f​o​n​t​ ​=​ ​f​o​n​t​;​
 ​ ​ ​ ​s​e​l​f​.​v​a​l​u​e​L​a​b​e​l​.​f​o​n​t​ ​=​ ​f​o​n​t​;​
}​

-​ ​(​v​o​i​d​)​a​w​a​k​e​F​r​o​m​N​i​b​
{​
 ​ ​ ​ ​[​s​e​l​f​ ​u​p​d​a​t​e​I​n​t​e​r​f​a​c​e​F​o​r​D​y​n​a​m​i​c​T​y​p​e​S​i​z​e​]​;​

 ​ ​ ​ ​N​S​N​o​t​i​f​i​c​a​t​i​o​n​C​e​n​t​e​r​ ​*​n​c​ ​=​ ​[​N​S​N​o​t​i​f​i​c​a​t​i​o​n​C​e​n​t​e​r​ ​d​e​f​a​u​l​t​C​e​n​t​e​r​]​;​
 ​ ​ ​ ​[​n​c​ ​a​d​d​O​b​s​e​r​v​e​r​:​s​e​l​f​
 ​ ​ ​ ​ ​ ​ ​ ​s​e​l​e​c​t​o​r​:​@​s​e​l​e​c​t​o​r​(​u​p​d​a​t​e​I​n​t​e​r​f​a​c​e​F​o​r​D​y​n​a​m​i​c​T​y​p​e​S​i​z​e​)​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​n​a​m​e​:​U​I​C​o​n​t​e​n​t​S​i​z​e​C​a​t​e​g​o​r​y​D​i​d​C​h​a​n​g​e​N​o​t​i​f​i​c​a​t​i​o​n​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​o​b​j​e​c​t​:​n​i​l​]​;​
}​

-​ ​(​v​o​i​d​)​d​e​a​l​l​o​c​
{​
 ​ ​ ​ ​N​S​N​o​t​i​f​i​c​a​t​i​o​n​C​e​n​t​e​r​ ​*​n​c​ ​=​ ​[​N​S​N​o​t​i​f​i​c​a​t​i​o​n​C​e​n​t​e​r​ ​d​e​f​a​u​l​t​C​e​n​t​e​r​]​;​
 ​ ​ ​ ​[​n​c​ ​r​e​m​o​v​e​O​b​s​e​r​v​e​r​:​s​e​l​f​]​;​
}​

The only new piece of information here is the awakeFromNib method. This is called on an object after it has been unarchived from a NIB file, and is a great place to do any additional UI work that cannot be done within the XIB file. You can do any additional configuration for the cell that cannot be done within the XIB file within this method. Build and run the application, and the text will update to reflect the user’s preferred text size.

Now there are a few Auto Layout issues that you need to resolve.

Initially, you pinned the height of nameLabel and serialNumberLabel. This does not work well now that your text sizes can dynamically change.

In BNRItemCell.xib, delete the two height constraints from those two labels. If you have any misplaced views now, open the Resolve Auto Layout Issues menu and select Update All Frames in Homepwner Item Cell. Build and run the application and the label heights will be based on the preferred text size.

The interface is looking fantastic now, but wouldn’t it be great if the size of imageView reflected the preferred font size? It makes sense that the image should scale with the text size. Let’s do this.

Constraint outlets

To update the position or size of a view, either in absolute terms or relative to another view, you should update the constraints on that view. This is very important! If you modify the frame (or bounds), instead of the constraints, the next time the view needs to be laid out, it will be laid out based on the constraints that it has. In other words, the changes made to the frame will not persist.

In order to change the width and height of the image view, the constants on the respective constraints will need to be updated at run time. To do this, you will need to create an outlet to both the vertical and horizontal constraints. Constraints are objects (NSLayoutConstraint), so just like you can create outlets to views, the same can be done with constraints.

In BNRItemCell.m, create and connect the outlet for these two constraints to the class extension. When you are done, the class extension should look like this:

@​i​n​t​e​r​f​a​c​e​ ​B​N​R​I​t​e​m​C​e​l​l​ ​(​)​

@​p​r​o​p​e​r​t​y​ ​(​n​o​n​a​t​o​m​i​c​,​ ​w​e​a​k​)​ ​I​B​O​u​t​l​e​t​ ​N​S​L​a​y​o​u​t​C​o​n​s​t​r​a​i​n​t​ ​*​i​m​a​g​e​V​i​e​w​H​e​i​g​h​t​C​o​n​s​t​r​a​i​n​t​;​
@​p​r​o​p​e​r​t​y​ ​(​n​o​n​a​t​o​m​i​c​,​ ​w​e​a​k​)​ ​I​B​O​u​t​l​e​t​ ​N​S​L​a​y​o​u​t​C​o​n​s​t​r​a​i​n​t​ ​*​i​m​a​g​e​V​i​e​w​W​i​d​t​h​C​o​n​s​t​r​a​i​n​t​;​

@​e​n​d​

With outlets to the size constraints of imageView created, you can now adjust imageView’s size programmatically. In BNRItemCell.m, modify updateInterfaceForDynamicTypeSize to get the currently selected preferred text size, and use that to adjust the size of imageView.

-​ ​(​v​o​i​d​)​u​p​d​a​t​e​I​n​t​e​r​f​a​c​e​F​o​r​D​y​n​a​m​i​c​T​y​p​e​S​i​z​e​
{​
 ​ ​ ​ ​U​I​F​o​n​t​ ​*​f​o​n​t​ ​=​ ​[​U​I​F​o​n​t​ ​p​r​e​f​e​r​r​e​d​F​o​n​t​F​o​r​T​e​x​t​S​t​y​l​e​:​U​I​F​o​n​t​T​e​x​t​S​t​y​l​e​B​o​d​y​]​;​
 ​ ​ ​ ​s​e​l​f​.​n​a​m​e​L​a​b​e​l​.​f​o​n​t​ ​=​ ​f​o​n​t​;​
 ​ ​ ​ ​s​e​l​f​.​s​e​r​i​a​l​N​u​m​b​e​r​L​a​b​e​l​.​f​o​n​t​ ​=​ ​f​o​n​t​;​
 ​ ​ ​ ​s​e​l​f​.​v​a​l​u​e​L​a​b​e​l​.​f​o​n​t​ ​=​ ​f​o​n​t​;​

 ​ ​ ​ ​s​t​a​t​i​c​ ​N​S​D​i​c​t​i​o​n​a​r​y​ ​*​i​m​a​g​e​S​i​z​e​D​i​c​t​i​o​n​a​r​y​;​

 ​ ​ ​ ​i​f​ ​(​!​i​m​a​g​e​S​i​z​e​D​i​c​t​i​o​n​a​r​y​)​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​i​m​a​g​e​S​i​z​e​D​i​c​t​i​o​n​a​r​y​ ​=​ ​@​{​ ​U​I​C​o​n​t​e​n​t​S​i​z​e​C​a​t​e​g​o​r​y​E​x​t​r​a​S​m​a​l​l​ ​:​ ​@​4​0​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​U​I​C​o​n​t​e​n​t​S​i​z​e​C​a​t​e​g​o​r​y​S​m​a​l​l​ ​:​ ​@​4​0​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​U​I​C​o​n​t​e​n​t​S​i​z​e​C​a​t​e​g​o​r​y​M​e​d​i​u​m​ ​:​ ​@​4​0​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​U​I​C​o​n​t​e​n​t​S​i​z​e​C​a​t​e​g​o​r​y​L​a​r​g​e​ ​:​ ​@​4​0​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​U​I​C​o​n​t​e​n​t​S​i​z​e​C​a​t​e​g​o​r​y​E​x​t​r​a​L​a​r​g​e​ ​:​ ​@​4​5​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​U​I​C​o​n​t​e​n​t​S​i​z​e​C​a​t​e​g​o​r​y​E​x​t​r​a​E​x​t​r​a​L​a​r​g​e​ ​:​ ​@​5​5​,​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​U​I​C​o​n​t​e​n​t​S​i​z​e​C​a​t​e​g​o​r​y​E​x​t​r​a​E​x​t​r​a​E​x​t​r​a​L​a​r​g​e​ ​:​ ​@​6​5​ ​}​;​
 ​ ​ ​ ​}​

 ​ ​ ​ ​N​S​S​t​r​i​n​g​ ​*​u​s​e​r​S​i​z​e​ ​=​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​[​[​U​I​A​p​p​l​i​c​a​t​i​o​n​ ​s​h​a​r​e​d​A​p​p​l​i​c​a​t​i​o​n​]​ ​p​r​e​f​e​r​r​e​d​C​o​n​t​e​n​t​S​i​z​e​C​a​t​e​g​o​r​y​]​;​

 ​ ​ ​ ​N​S​N​u​m​b​e​r​ ​*​i​m​a​g​e​S​i​z​e​ ​=​ ​i​m​a​g​e​S​i​z​e​D​i​c​t​i​o​n​a​r​y​[​u​s​e​r​S​i​z​e​]​;​
 ​ ​ ​ ​s​e​l​f​.​i​m​a​g​e​V​i​e​w​H​e​i​g​h​t​C​o​n​s​t​r​a​i​n​t​.​c​o​n​s​t​a​n​t​ ​=​ ​i​m​a​g​e​S​i​z​e​.​f​l​o​a​t​V​a​l​u​e​;​
 ​ ​ ​ ​s​e​l​f​.​i​m​a​g​e​V​i​e​w​W​i​d​t​h​C​o​n​s​t​r​a​i​n​t​.​c​o​n​s​t​a​n​t​ ​=​ ​i​m​a​g​e​S​i​z​e​.​f​l​o​a​t​V​a​l​u​e​;​

}​

Build and run the application, and play with the Dynamic Type text sizes. The imageView adjusts its size appropriately. Also notice that because you pinned the leading edge of nameLabel and serialNumberLabel to the trailing edge of the imageView, the interface scales very well as the preferred text size changes. Had those two labels been pinned to their superview’s leading edge instead, the imageView would have overlapped the labels.

The interface is great, but let’s make one final change.

Placeholder constraints

Currently, you are updating both the width and height constraints for the imageView. This is not a problem, but you can do better. Instead of updating both constraints, you will add one additional constraint to imageView that will constrain the imageView’s width and height to be equal.

You cannot create this constraint in Interface Builder, so return to BNRItemCell.m and create this constraint programmatically in awakeFromNib.

-​ ​(​v​o​i​d​)​a​w​a​k​e​F​r​o​m​N​i​b​
{​
 ​ ​ ​ ​[​s​e​l​f​ ​u​p​d​a​t​e​I​n​t​e​r​f​a​c​e​F​o​r​D​y​n​a​m​i​c​T​y​p​e​S​i​z​e​]​;​

 ​ ​ ​ ​N​S​N​o​t​i​f​i​c​a​t​i​o​n​C​e​n​t​e​r​ ​*​n​c​ ​=​ ​[​N​S​N​o​t​i​f​i​c​a​t​i​o​n​C​e​n​t​e​r​ ​d​e​f​a​u​l​t​C​e​n​t​e​r​]​;​
 ​ ​ ​ ​[​n​c​ ​a​d​d​O​b​s​e​r​v​e​r​:​s​e​l​f​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​s​e​l​e​c​t​o​r​:​@​s​e​l​e​c​t​o​r​(​u​p​d​a​t​e​I​n​t​e​r​f​a​c​e​F​o​r​D​y​n​a​m​i​c​T​y​p​e​S​i​z​e​)​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​n​a​m​e​:​U​I​C​o​n​t​e​n​t​S​i​z​e​C​a​t​e​g​o​r​y​D​i​d​C​h​a​n​g​e​N​o​t​i​f​i​c​a​t​i​o​n​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​o​b​j​e​c​t​:​n​i​l​]​;​

 ​ ​ ​ ​N​S​L​a​y​o​u​t​C​o​n​s​t​r​a​i​n​t​ ​*​c​o​n​s​t​r​a​i​n​t​ ​=​
 ​ ​ ​ ​ ​ ​ ​ ​[​N​S​L​a​y​o​u​t​C​o​n​s​t​r​a​i​n​t​ ​c​o​n​s​t​r​a​i​n​t​W​i​t​h​I​t​e​m​:​s​e​l​f​.​t​h​u​m​b​n​a​i​l​V​i​e​w​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​a​t​t​r​i​b​u​t​e​:​N​S​L​a​y​o​u​t​A​t​t​r​i​b​u​t​e​H​e​i​g​h​t​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​r​e​l​a​t​e​d​B​y​:​N​S​L​a​y​o​u​t​R​e​l​a​t​i​o​n​E​q​u​a​l​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​t​o​I​t​e​m​:​s​e​l​f​.​t​h​u​m​b​n​a​i​l​V​i​e​w​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​a​t​t​r​i​b​u​t​e​:​N​S​L​a​y​o​u​t​A​t​t​r​i​b​u​t​e​W​i​d​t​h​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​m​u​l​t​i​p​l​i​e​r​:​1​
 ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​c​o​n​s​t​a​n​t​:​0​]​;​
 ​ ​ ​ ​[​s​e​l​f​.​t​h​u​m​b​n​a​i​l​V​i​e​w​ ​a​d​d​C​o​n​s​t​r​a​i​n​t​:​c​o​n​s​t​r​a​i​n​t​]​;​
}​

Now, remove the imageViewWidthConstraint property and corresponding code.

@​i​n​t​e​r​f​a​c​e​ ​B​N​R​I​t​e​m​C​e​l​l​ ​(​)​

@​p​r​o​p​e​r​t​y​ ​(​n​o​n​a​t​o​m​i​c​,​ ​w​e​a​k​)​ ​I​B​O​u​t​l​e​t​ ​N​S​L​a​y​o​u​t​C​o​n​s​t​r​a​i​n​t​ ​*​i​m​a​g​e​V​i​e​w​H​e​i​g​h​t​C​o​n​s​t​r​a​i​n​t​;​
@​p​r​o​p​e​r​t​y​ ​(​n​o​n​a​t​o​m​i​c​,​ ​w​e​a​k​)​ ​I​B​O​u​t​l​e​t​ ​N​S​L​a​y​o​u​t​C​o​n​s​t​r​a​i​n​t​ ​*​i​m​a​g​e​V​i​e​w​W​i​d​t​h​C​o​n​s​t​r​a​i​n​t​;​

@​e​n​d​

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

-​ ​(​v​o​i​d​)​u​p​d​a​t​e​I​n​t​e​r​f​a​c​e​F​o​r​D​y​n​a​m​i​c​T​y​p​e​S​i​z​e​
{​
 ​ ​ ​ ​/​/​ ​O​t​h​e​r​ ​c​o​d​e​ ​h​e​r​e​

 ​ ​ ​ ​N​S​N​u​m​b​e​r​ ​*​i​m​a​g​e​S​i​z​e​ ​=​ ​i​m​a​g​e​S​i​z​e​D​i​c​t​i​o​n​a​r​y​[​u​s​e​r​S​i​z​e​]​;​
 ​ ​ ​ ​s​e​l​f​.​i​m​a​g​e​V​i​e​w​H​e​i​g​h​t​C​o​n​s​t​r​a​i​n​t​.​c​o​n​s​t​a​n​t​ ​=​ ​i​m​a​g​e​S​i​z​e​.​f​l​o​a​t​V​a​l​u​e​;​
 ​ ​ ​ ​s​e​l​f​.​i​m​a​g​e​V​i​e​w​W​i​d​t​h​C​o​n​s​t​r​a​i​n​t​.​c​o​n​s​t​a​n​t​ ​=​ ​i​m​a​g​e​S​i​z​e​.​f​l​o​a​t​V​a​l​u​e​;​
}​

Open BNRItemCell.xib and make sure that the outlet for imageViewWidthConstraint is removed, since the outlet no longer exists.

There is one final change that must be made. There are now two constraints affecting the width of the imageView: the programmatic constraint you just created and the explicit width constraint in the XIB file. This will create unsatisfiable (conflicting) constraints if the two constraints do not agree on a size.

To fix this, you could delete the explicit width constraint from the imageView. This will work, but Interface Builder might warn about misplaced views or an ambiguous layout. Instead, you can make the width constraint a placeholder constraint. Placeholder constraints, as the name implies, are only temporary and are removed at build time, so they will not exist when the application is running.

In BNRItemCell.xib, select the width constraint on the imageView, and open the attributes inspector. Check the Placeholder box that says Remove at build time (Figure 20.6). Build and run the application, and everything will work just as it did before. Homepwner now scales appropriately with the user’s preferred text size.

Figure 20.6  Placeholder constraints

Placeholder constraints
..................Content has been hidden....................

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