iOS Programming Dynamic Type 2,iosprogramming


iOS Programming Dynamic Type 2,iosprogramming

iOS Programming Dynamic Type  2 

     You will need to update two parts of this view controller for Dynamic Type: the rows of your table view will grow or shrink in response to the user changing the preferred text size, and the BNRItemCell will need to be updated similarly to how you updated the BNRDetailViewController.

你的table view的row將會增大或縮小來響應使用者改變preferred text size,BNRItemCell 將會知道怎樣更新在BNRDetailViewController。

The goal is to have the table view row heights reflect the preferred Dynamic Type text size of the user.

目的是讓table view row height 反應preferred Dynamic Type text size 。

If the user chooses a larger text size, the rows will be taller in order to accommodate the text.

如果使用者選擇了一個更大的text size,rows 將會變高來適應text。

Since this is not a problem that Auto Layout will solve, the row heights will need to be set manually.

因為auto layout 將解決,這不是問題,row heights將設定為手動。

To do this, you need a way of determining which text size the user has selected.

為了這樣做,你需要一種方式決定哪個text size 使用者想選擇。

UIApplication exposes the text size that user selected through its preferredContentSizeCategory property.

UIApplication 報了出使用者選擇的text size 通過它的 preferredContentSizeCategory屬性。

The method will return a constant NSString with the name of the content size category,

這個方法將返回一個content size category 名字的字串。

which will be one of the following values:




(4)UIContentSizeCategoryLarge (Default) 




Open BNRItemsViewController.m. Create a method that will update the table view row height based on the user-selected text size and call this method in viewWillAppear:.


[self updateTableViewForDynamicTypeSize];


Just as you did with the BNRDetailViewController earlier, you need to have the BNRItemsViewController register itself as an observer for the UIContentSizeCategoryDidChangeNotification.



In BNRItemsViewController.m, register for the notification in init, and remove the view controller as an observer in dealloc. Finally, implement the notification call back to call the updateTableViewForDynamicTypeSize method that you just created.


NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

[nc addObserver:self

selector:@selector(updateTableViewForDynamicTypeSize) name:UIContentSizeCategoryDidChangeNotification



- (void)dealloc

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

[nc removeObserver:self];




Deallocates the memory occupied by the receiver.


Subsequent messages to the receiver may generate an error indicating that a message was sent to a deallocated object (provided the deallocated memory hasn't been reused yet).

隨後發給接受者的訊息可能產生一個錯誤顯示這個訊息已經發送給了deallocated object.

You override this method to dispose of resources other than the object's instance variables, 

你重寫該方法除了對象的執行個體變數,你還dispose 資源。

for example:

- (void)dealloc {




2.1 dealloc 

In an implementation of dealloc, do not invoke the superclass's implementation. 


You should try to avoid managing the lifetime of limited resources such as file descriptors using dealloc.


You never send a dealloc message directly. Instead, an object's dealloc method is invoked by the runtime. 

你從不直接發送一個dealloc 訊息。一個對象的dealloc方法會在運行時被調用。

When not using ARC, your implementation of dealloc must invoke the superclass's implementation as its last instruction.

當不適用ARC時,你實現的dealloc 必須調用它的superclass的實現作為它最後的指令。


You don't need dealloc method in ARC.

你不需要在arc中使用dealloc 。

But if you want to do some cleanup tasks when your view is dismissing or released. It's the best place, In such case you can implement it.

但是當你的view 被dismissing 或released時,你想做一些cleanup 任務。這是你最好的位置。在這種情況下,你可以實現它。


You are running a timer in your view and it's updating your view. When you are dismissed the view you need to stop that timer. In that condition you can use dealloc method and stop timer there.

你在你的view裡運行了一個timer。當你dismissed 這個view,你需要停止掉timer。在這種情況下,你需要用dealloc 方法,停掉timer 在這裡。


You are therefore allowed to subclass dealloc under ARC, but you are not allowed to call [super dealloc] from within the subclassed method.

當在ARC 下,不允許調用[super dealloc]

3. Updating BNRItemCell

Let's begin by implementing the Dynamic Type code to update the labels, which will closely follow what you did with BNRDetailViewController and BNRItemsViewController.

讓我們開始實現Dynamic Type code 來更新labels。

Open BNRItemCell.m and make the following changes:

-  (void)updateInterfaceForDynamicTypeSize

UIFont *font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];

self.nameLabel.font = font;

self.serialNumberLabel.font = font;
self.valueLabel.font = font;


-  (void)awakeFromNib
[self updateInterfaceForDynamicTypeSize];
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; [nc addObserver:self
selector:@selector(updateInterfaceForDynamicTypeSize) name:UIContentSizeCategoryDidChangeNotification 




- (void)dealloc

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

[nc removeObserver:self]; }


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.


4 Constraint outlets 

It makes sense that the image should scale with the text size. Let's do this.

讓image圖片和text size 一起放縮。

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.

為了更新一個view 的位置或尺寸,不管是絕對或者與另一個view 相關,你應該更新這些view上的constraints.

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.

為了改變image view 的寬和高,在各自的限制上都應該在運行時發生變化。

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.

Constraints 是對象(NSLayoutConstraint),所以你就像建立view 的outlet一樣建立constraints。


疑問:如果是Programming 編寫的,怎麼設定outlet呢?


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:

@interface BNRItemCell ()

@property (nonatomic, weak) IBOutlet NSLayoutConstraint *imageViewHeightConstraint;
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *imageViewWidthConstraint;


With outlets to the size constraints of imageView created, you can now adjust imageView's size programmatically.

由於這些imageView的限制,你現在能夠通過programmatically 來調整imageView的尺寸了。

In BNRItemCell.m, modify updateInterfaceForDynamicTypeSize to get the currently selected preferred text size, and use that to adjust the size of imageView.

擷取當前選擇的text  size ,用來調整image view 的尺寸。

static NSDictionary *imageSizeDictionary;

if (!imageSizeDictionary) {

imageSizeDictionary = @{ UIContentSizeCategoryExtraSmall : @40,

UIContentSizeCategorySmall : @40, UIContentSizeCategoryMedium : @40, UIContentSizeCategoryLarge : @40, UIContentSizeCategoryExtraLarge : @45, UIContentSizeCategoryExtraExtraLarge : @55, UIContentSizeCategoryExtraExtraExtraLarge : @65 };

NSString *userSize = [[UIApplication sharedApplication] preferredContentSizeCategory];

NSNumber *imageSize = imageSizeDictionary[userSize];

self.imageViewHeightConstraint.constant = imageSize.floatValue;

self.imageViewWidthConstraint.constant = imageSize.floatValue;


4 Placeholder constraints

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.

而不是更新兩個constraints,你可以給imageView添加一個constraint:constrain the imageView的寬和高相等。

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

你不能在Interface Builder,所以你可以返回BNRItemCell.m,在awakeFromNib內建立這些constraint通過編程。

NSLayoutConstraint *constraint =
[NSLayoutConstraint constraintWithItem:self.thumbnailView

attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual

toItem:self.thumbnailView attribute:NSLayoutAttributeWidth

multiplier:1 constant:0];

[self.thumbnailView addConstraint:constraint];


Now, remove the imageViewWidthConstraint property and corresponding code.

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.

如果這兩個限制沒有達成一致,則會出現unsatisfiable constraints.

Instead, you can make the width constraint a placeholder constraint.

取而'之的是你可以製造width constraint 為一個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.

placeholder constraints ,正如名字隱含的那樣,僅僅是臨時的,在build time 就移除了,所以當application運行是他們就不存在了。

n BNRItemCell.xib, select the width constraint on the imageView, and open the attributes inspector. Check the Placeholder box that says Remove at build time








Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >



如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。