(BQ) Part 2 book IOS programming The big nerd ranch guide has contents Subclassing UITable view cell, uinavigationcontroller, stack views, touch events and uiresponder, uigesturerecognizer and uimenucontroller, web services, collection views, core data relationships,...and other contents.
Trang 111 Subclassing UITableViewCell
Item’s name, its value in dollars, and its serial number (Figure 11.1)
Figure 11.1 Homepwner with subclassed table view cells
You customize the appearance of UITableViewCell subclasses by adding subviews to
its contentView Adding subviews to the contentView instead of directly to the cellitself is important because the cell will resize its contentView at certain times Forexample, when a table view enters editing mode, the contentView resizes itself tomake room for the editing controls (Figure 11.2) If you added subviews directly to the
UITableViewCell, these editing controls would obscure the subviews The cell cannotadjust its size when entering edit mode (it must remain the width of the table view), butthe contentView can resize, and it does
Trang 2Figure 11.2 Table view cell layout in standard and editing mode
Trang 3Create a new Swift file named ItemCell In ItemCell.swift, define ItemCell as
a UITableViewCell subclass.
i pr o na in
i pr I i
c as Ie Cl :U Tb ei we l{
Trang 45 Select the bottom-left label and open its size inspector Find the Vertical Content Hugging Priority and lower it to 250 Lower the Vertical Content Compression Resistance Priority to 749 You will learn what these Auto Layout properties do in Chapter 12.
6 Your frames might be misplaced, so open the Resolve Auto Layout Issues menu andupdate the frames for the three labels
Trang 6For ItemsViewController to configure the content of an ItemCell in
tableView(_:cellForRowAtIndexPath:), the cell must have properties thatexpose the three labels These properties will be set through outlet connections in
Main.storyboard
The next step, then, is to create and connect outlets on ItemCell for each of its
subviews
Open ItemCell.swift and add three properties for the outlets
i pr I i
c as Ie Cl :U Tb ei we l{
@ Bu lt vr nm Lb l Ia e!
@ Bu lt vr sr aN me Lb l Ia e!
@ Bu lt vr vl ea e: UL bl
}
You are going to connect the outlets for the three views to the ItemCell When
connecting outlets earlier in the book, you Control-dragged from view controller in the
storyboard to the appropriate view But the outlets for ItemCell are not outlets on a controller They are outlets on a view: the custom UITableViewCell subclass.
Trang 8height of the table view cells
o er d uc ve Dd od ){
s pr ve Dd od )
/ e h e gt o h tt sb r
l ts au Br eg t= UA pi ai ns ae Ap i ai n) sa uB rr m. eg t
l ti st Id en es tp t ts aH ih , lf :0 o tm , rg t )
t be iw cn et ne ne s
t be iw sr lI dc tr ne s= is t
t be iw rw eg t= 6
o er d uc tb ei wt be iw I al Ve ,
c lF ro AI dx ah id xa h Sn eP t )- I al Ve Cl
/ e e rr cc e el
l tc l a lV e. eu uR ua lC lW tI e tf e( UT be iw el ,
f rn eP t: id xa h
l tc l a lV e. eu uR ua lC lW tI e tf e( Ie Cl "
f rn eP t: id xa h s tm el
/ e h e to h e lw t h ec it o f te ie
/ h ti t te nh id xo t m, we en = rw ti e l
/ i la pa n o h al ve
l ti e t mt r. lI es id xa hr w
c l. et ae ?t x t mn m
c l. ea le ta e? tx $( tm vl en o lr )
/ o fg r h el wt h t m
c l. ae ae e t= ie a e
c l. ei lu br ae e t= ie e il ub r
c l. au Lb lt x $ (t mv le no lr )
r tr e l
}
First, the reuse identifier is updated to reflect your new subclass The code at the end ofthis method is fairly obvious – for each label on the cell, set its text to some property
from the appropriate Item.
Trang 9values from each Item.
Trang 11Currently, the cells have a fixed height of 65 points It is much better to allow the content
of the cell to drive its height That way, if the content ever changes, the table view cell’sheight can change automatically
You can achieve this goal, as you have probably guessed, with Auto Layout The
UITableViewCell needs to have vertical constraints that will exactly determine the
height of the cell Currently, ItemCell does not have sufficient constraints for this You
need to add a constraint between the two left labels that fixes the vertical spacing betweenthem
/ e h e gt o h tt sb r
l ts au Br eg t= UA pi ai ns ae Ap i ai n) sa uB rr m. eg t
l ti st Id en es tp t ts aH ih , lf :0 o tm , rg t )
t be iw cn et ne ne s
t be iw sr lI dc tr ne s= is t
t be iw rw eg t= 6
t be iw rw eg t= UT be iw uo ai Dm n in
t be iw et mt do Hi h 5
Build and run the application The application will look the same as it did before In the
next section, you will learn about a technology called Dynamic Type that will take
advantage of the automatically resizing table view cells
Trang 13Creating an interface that appeals to everyone can be daunting Some people prefer morecompact interfaces so they can see more information at a time Others might want to beable to easily see information at a glance, or perhaps they have poor eyesight In short:people have different needs Good developers strive to make apps that meet those needs.Dynamic Type is a technology that helps realize this goal by providing specifically
different text styles
Trang 14Open Main.storyboard Let’s update the labels to use the text styles instead of fixedfonts Select the nameLabel and valueLabel and open the attributes inspector Click on the texticon to the right of Font For Font, choose Text Styles - Body (Figure 11.8) Repeat the samesteps for the serialNumberLabel, choosing the Caption 1 text style
Figure 11.8 Changing the text style
Now let’s change the preferred font size You do this through the Settings application
Build and run the application Press the Home button (or use Home from the Hardware
Trang 15Larger Text (On an actual device, this menu is accessed in Settings under Display & Brightness
and then Text Size.) Drag the slider all the way to the left to set the font size to the smallestvalue (Figure 11.9) Press the Home button again to save these changes
Figure 11.9 Text size settings
Build and run the application (If you switch back to the application, either using the taskswitcher or through the Home screen, you will not see the changes You will fix that in thenext section.) Add some items to the table view and you will see the new smaller fontsizes in action
Responding to user changes
When the user changes the preferred text size and returns to the application, the table viewwill get reloaded Unfortunately, the labels will not know about the new preferred text
Trang 16Open ItemCell.swift and add a new method that updates all three labels
f n pa ea es ){
l tb dF n I ot pe er do to Tx Sy e UF nT xS ye oy
n mL bl fn oy ot
v le ae o t= bd Fn
l tc pi nF n I ot pe er do to Tx S ye UF nT xS ye at o1
s ra Nm eL bl fn at o1 ot
}
Now open ItemsViewController.swift and call this method in
o er d uc tb ei wt be iw I al Ve ,
c lF ro AI dx ah id xa h Sn eP t) - I al Ve Cl
/ e e rr cc e el
l tc l a lV e. eu uR ua lC lW t Ie tf e( UT be iw el ,
f rn eP t: id xa h s tm el
/ p ae te lb l o h e rf re et sz
c l. pa ea es )
l ti e t mt r. lI es id xa hr w
c l. ae ae e t= ie a e
c l. ei lu br ae e t= ie e il u br
c l. au Lb lt x $ (t mv le no l r)
r tr e l
}
Build and run the application Go into Settings and change the preferred reading size to thelargest size Unlike before, you can now switch back to Homepwner, either by opening thetask switcher or through the Home screen, and the table view will update to reflect thenew preferred text size
Trang 18Update the ItemCell to display the valueInDollars in green if the value is less
than 50 and red if the value is greater than or equal to 50
Trang 2012 Stack Views
You have been using Auto Layout throughout this book to create flexible interfaces thatscale across device types and sizes Auto Layout is a very powerful technology, but withthat power comes complexity Laying out an interface well often needs a lot of constraints,and it can be difficult to create dynamic interfaces due to the need to constantly add andremove constraints
Often, an interface (or a subsection of the interface) can be laid out in a linear fashion.Let’s think about some of the other applications you have written in this book The Quiz
application that you wrote in Chapter 1 consisted of four subviews that were laid out
vertically The same is true for the WorldTrotter application that you wrote: the
ConversionViewController had a vertical interface consisting of a text field and afew labels
Interfaces that have a linear layout are great candidates for using a stack view A stack
view is an instance of UIStackView that allows you to create a vertical or horizontal
layout that is easy to lay out and manages most of the constraints that you would typicallyhave to manage yourself Perhaps best of all, you are able to nest stack views within otherstack views, which allows you to create truly amazing interfaces in a fraction of the time
In this chapter, you are going to continue working on Homepwner to create an interface for
displaying the details of a specific Item The interface that you create will consist of
multiple nested stack views, both vertical and horizontal (Figure 12.1)
Trang 21Figure 12.1 Homepwner with stack views
Trang 22Open your Homepwner project and then open Main.storyboard Drag a new View
Controller from the object library onto the canvas Drag a Vertical Stack View from the objectlibrary onto the view for the View Controller Add constraints to the stack view to pin it to theleading and trailing margins, and pin the top and bottom edges to be 8 points from the topand bottom layout guides
Now drag four instances of UILabel from the object library onto the stack view From
top to bottom, give these labels the text “Name,” “Serial,” “Value,” and “Date Created.”(Figure 12.3)
Trang 23You can see a problem right away: the labels all have a red border (indicating an AutoLayout problem) and there is a warning that some views are vertically ambiguous Thereare two ways you can fix this issue: by using Auto Layout, or by using a property on thestack view Let’s work through the Auto Layout solution first because it highlights animportant aspect of Auto Layout
Implicit constraints
You learned in Chapter 3 that every view has an intrinsic content size You also learnedthat if you do not specify constraints that explicitly determine the width or height, theview will derive its width or height from its intrinsic content size How does this work?
It does this using implicit constraints derived from a view’s content hugging priorities and its content compression resistance priorities A view has one of these priorities for each
axis:
horizontal content hugging priority
Trang 24to one another with constraints both between the two views and between each view and itssuperview, as shown in Figure 12.4
Figure 12.4 Two labels side by side
This works great until the superview becomes wider At that point, which label shouldbecome wider? The first label, the second label, or both? As Figure 12.5 shows, the
interface is currently ambiguous
Figure 12.5 Ambiguous layout
This is where the content hugging priority becomes relevant The view with the highercontent hugging priority is the one that does not stretch You can think about the priorityvalue as the “strength” of the rubber band The higher the priority value, the stronger the
Trang 25Content compression resistance priorities
The content compression resistance priorities determine how much a view resists gettingsmaller than its intrinsic content size Consider the same two labels from Figure 12.4.What would happen if the superview’s width decreased? One of the labels would need totruncate its text (Figure 12.6) But which one?
Figure 12.6 Compressed ambiguous layout
The view with the greater content compression resistance priority is the one that will resistcompression and, therefore, not truncate its text
Select the stack view, either on the canvas or using the document outline Open its
attributes inspector and find the section at the top labeled Stack View One of the propertiesthat determines how the content is laid out is the Distribution property Currently it is set to
Fill, which lets the views lay out their content based on their intrinsic content size Changethe value to Fill Equally This will resize the labels so that they all have the same height,ignoring the intrinsic content size (Figure 12.7) Be sure to read the documentation for theother distribution values that a stack view can have
Trang 26Select the Name label on the canvas Click the left-most icon in the Auto Layout
constraints menu: This will embed the selected view in a stack view
Select the new stack view and open its attributes inspector The stack view is currently avertical stack view, but you want it to be a horizontal stack view Change the Axis to
Horizontal
Now drag a Text Field from the object library to the right of the Name label Since labels, by
Trang 27intrinsic content width and the text field stretches The label and the text field currentlyhave the same content compression resistance priorities, which would result in an
ambiguous layout if the text field’s text was too long Open the size inspector for the textfield and set its Horizontal Content Compression Resistance Priority to 749
Stack view spacing
The label and text field look a little squished since there is no spacing between them.Stack views allow you to customize the spacing between items
Select the horizontal stack view and open its attributes inspector Change the Spacing to be
8 points Notice that the text field shrinks to accommodate the spacing, because it is lessresistant to compression than the label
Repeat these same steps for the Serial and Value labels
1 Select the label and click the icon
2 Change the stack view to be a horizontal stack view
3 Drag a text field onto the horizontal stack view and change its horizontal contentcompression resistance priority to be 749
4 Update the stack view to have a spacing of 8 points
There are a couple of other tweaks you will want to make to the interface The verticalstack view needs some spacing The Date Created label should have a center text alignment.And the Name, Serial, and Value labels should be the same width
Select the vertical stack, open its attributes inspector, and update the Spacing to be 8 points.Then select the Date Created label, open its attributes inspector, and change the Alignment to
be centered That solves the first two issues
Although stack views substantially reduce the number of constraints that you need to add
to your interface, some constraints are still important With the interface as is, the textfields do not align on their leading edge due to the difference in the widths of the labels.(The difference is not very noticeable in English, but it becomes more pronounced whenlocalized into other languages.) To solve this, you will add leading edge constraints
between the three text fields
Control-drag from the Name text field to the Serial text field and select Leading Then do thesame for the Serial text field and the Value text field The completed interface will look like
Figure 12.8
Trang 28Stack views allow you to create very rich interfaces in a fraction of the time it would take
to configure them manually using constraints Constraints are still added, but they arebeing managed by the stack view itself instead of by you Stack views allow you to havevery dynamic interfaces at runtime You can add and remove views from stack views by
using addArrangedSubview(_:), insertArrangedSubview(_:atIndex:), and removeArrangedSubview(_:) You can also toggle the hidden property on a
view in a stack view The stack view will automatically lay out its content to reflect thatvalue
Trang 30In Main.storyboard, select the ItemCell prototype cell on the Items View Controller.Control-drag from the cell to the new view controller that you set up in the previous
section (Make sure you are Control-dragging from the cell and not the table view!) Ablack panel will appear that lists the possible styles for this segue Select Show from the
Selection Segue section (Figure 12.9)
Figure 12.9 Setting up a show segue
Notice the arrow that goes from the table view controller to the new view controller This
is a segue The icon in the circle tells you that this segue is a show segue – each segue has
Trang 31Build and run the application Tap a cell and the new view controller will slide up from thebottom of the screen (Sliding up from the bottom is the default behavior when presenting
a view controller modally This can be customized, however, as you saw in Chapter 10
when you presented the UIAlertController modally.)
So far, so good! But there are two problems at the moment: the view controller is not
displaying the information for the Item that was selected, and there is no way to dismiss the view controller to return to the ItemsViewController You will fix the first issue
in the next section, and you will fix the second issue in Chapter 13
Trang 33i pr o na in
i pr I i
c as Dt iV eC nr le :U Ve Cn rl e
Your window has become a little cluttered Let’s make some temporary space Hide thenavigator area by clicking the left button in the View control at the top of the workspace(the shortcut for this is Command-0) Then, hide the document outline in Interface Builder byclicking the toggle button in the lower left corner of the editor Your workspace shouldnow look like Figure 12.10
Trang 35Let go and a pop-up window will appear Enter nameField into the Name field, select
Strong from the Storage pop-up menu, and click Connect (Figure 12.13)
Trang 36After making the connections, DetailViewController.swift should look likethis:
i pr I i
c as Dt iV eC nr le :U Ve Cn rl e
@ Bu lt vr nm Fe d Ie ti l!
@ Bu lt vr sr aN me Fe d Ie ti l!
@ Bu lt vr vl ei l: UT xF ed
@ Bu lt vr dt Lb l Ia e!
}
If your file looks different, then your outlets are not connected correctly Fix any
disparities between your file and the code shown above in three steps: First, go throughthe Control-drag process and make connections again until you have the four lines shownabove in your DetailViewController.swift Second, remove any wrong code(like non-property method declarations or properties) that got created Finally, check forany bad connections in the storyboard file In Main.storyboard, Control-click on the
Detail View Controller If there are yellow warning signs next to any connection, click the x
icon next to those connections to disconnect them
It is important to ensure that there are no bad connections in an interface file A bad
connection typically happens when you change the name of a property but do not updatethe connection in the interface file Or, you completely remove a property but do notremove it from the interface file Either way, a bad connection will cause your application
to crash when the interface file is loaded
Trang 37DetailViewController will hold on to a reference to the Item that is being
displayed When its view is loaded, you will set the text on each text field to the
appropriate value from the Item instance.
In DetailViewController.swift, add a property for an Item instance and override viewWillAppear(_:) to set up the interface.
c as Dt iV eC nr le :U Ve Cn rl e
@ Bu lt vr nm Fe d Ie ti l!
@ Bu lt vr sr aN me Fe d Ie ti l!
@ Bu lt vr vl ei l: UT xF ed
@ Bu lt vr dt Lb l Ia e!
v ri e: Ie !
o er d uc ve Wl Ap a( nm td o l
s pr ve Wl Ap a( nm td
n mF ed tx tm nm
s ra Nm eF ed tx tm sr aN me
v le il e t= "( tm vl en ol r)
d tL bl tx \i e. ae ra e)
v ri e: Ie !
l tn me Fr at r Su br om te
l tf ra tr =N Nm eF ra tr )
f ra tr nm eS ye =. ei aS ye
f ra tr mn mm rc in ii s= 2
f ra tr mx mm rc in ii s= 2
r tr o mt e
} )
l td tF ra tr S ae om te
l tf ra tr =N Dt Fr at r)
f ra tr dt Sy e= e im tl
f ra tr tm Sy e= o tl
r tr o mt e
} )
o er d uc ve Wl Ap a( nm td o l
s pr ve Wl Ap a( nm td
n mF ed tx tm nm
s ra Nm eF ed tx tm sr aN me
v le il e t= "( tm vl en ol r)
d tL bl tx \i e. ae ra e)
v le il e t= nm eF ra tr sr nF oN m e( tm vl en ol r)
d tL bl tx ae om te t ig rm ae i e. ae ra e)
Trang 39between the two view controllers and open the attributes inspector For the identifier, enterShowItem (Figure 12.15)
Figure 12.15 Segue identifier
With your segue identified, you can now pass your Item instances around Open
ItemsViewController.swift and implement
o er d uc pe ae oS ge sg e It rb ad e u, sn e: Ay be t) {
/ f te ti gr ds ge i h So Ie "s g e
i e u. dn ii r= S oI e" {
/ i ue ot wi hr ww sj s ap d
i e o al Ve n eP tF re et d o? rw {
/ e h t ma sc ae i ht i o n a si l n
l ti e t mt r. lI es rw
l td ti Ve Cn rl e
= sg ed si ai ni wo to l ra !D ti Ve Cn rl e
d ti Ve Cn rl e. tm =i e
}
}
}
Build and run the application Tap on a row and the DetailViewController will