Developing For Apple TV Using TvOS and Swift
Developing For Apple TV Using TvOS and Swift
for Apple TV
using tvOS and Swift
—
Gary Bennett
Stefan Kaczmarek
Brad Lees
S
AR
IN
EB
GW
IN
AIN
www.allitebooks.com TR
Developing for
Apple TV using
tvOS and Swift
Gary Bennett
Stefan Kaczmarek
Brad Lees
www.allitebooks.com
Developing for Apple TV using tvOS and Swift
Copyright © 2015 by Gary Bennett, Stefan Kaczmarek and Brad Lees
This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part
of the material is concerned, specifically the rights of translation, reprinting, reuse of illustrations,
recitation, broadcasting, reproduction on microfilms or in any other physical way, and transmission
or information storage and retrieval, electronic adaptation, computer software, or by similar or
dissimilar methodology now known or hereafter developed. Exempted from this legal reservation are
brief excerpts in connection with reviews or scholarly analysis or material supplied specifically for
the purpose of being entered and executed on a computer system, for exclusive use by the purchaser
of the work. Duplication of this publication or parts thereof is permitted only under the provisions
of the Copyright Law of the Publisher’s location, in its current version, and permission for use must
always be obtained from Springer. Permissions for use may be obtained through RightsLink at the
Copyright Clearance Center. Violations are liable to prosecution under the respective Copyright Law.
ISBN-13 (pbk): 978-1-4842-1714-6
ISBN-13 (electronic): 978-1-4842-1715-3
Trademarked names, logos, and images may appear in this book. Rather than use a trademark
symbol with every occurrence of a trademarked name, logo, or image we use the names, logos, and
images only in an editorial fashion and to the benefit of the trademark owner, with no intention of
infringement of the trademark.
The use in this publication of trade names, trademarks, service marks, and similar terms, even if they
are not identified as such, is not to be taken as an expression of opinion as to whether or not they are
subject to proprietary rights.
While the advice and information in this book are believed to be true and accurate at the date of
publication, neither the authors nor the editors nor the publisher can accept any legal responsibility
for any errors or omissions that may be made. The publisher makes no warranty, express or implied,
with respect to the material contained herein.
www.allitebooks.com
Gary would like to dedicate this book to wife Stefanie and children,
Michael, Danielle, Michelle, and Emily, for always supporing him.
Stefan would like to dedicate this book to his wife Veronica for
supporting him throughout all of life’s adventures.
Brad would like to dedicate this book to his wife Natalie for
always supporting him. He couldn’t do it without her.
www.allitebooks.com
Contents at a Glance
■
■Chapter 1: Getting Started with the New Apple TV������������������������� 1
■
■Chapter 2: The tvOS Weather App��������������������������������������������������� 9
■
■Chapter 3: Stack Views and the Focus Engine����������������������������� 23
■
■Chapter 4: Creating a Photo Gallery App�������������������������������������� 33
■
■Chapter 5: Adding an Album Browser to the Photo Gallery App���� 57
■■Chapter 6: Adding a Dynamic Top Shelf to the
Photo Gallery App������������������������������������������������������������������������� 75
■
■Chapter 7: Storing and Sharing Data�������������������������������������������� 93
■
■Chapter 8: CloudKit��������������������������������������������������������������������� 105
Index���������������������������������������������������������������������������������������������� 123
www.allitebooks.com
Contents
■
■Chapter 1: Getting Started with the New Apple TV������������������������� 1
Lots of Good News���������������������������������������������������������������������������������� 1
Capabilities��������������������������������������������������������������������������������������������������������������� 1
The Siri Remote�������������������������������������������������������������������������������������������������������� 4
Apple TV’s Limitations���������������������������������������������������������������������������������������������� 5
Advantages with tvOS Development������������������������������������������������������������������������� 6
Some Notes About Developing in Swift with tvOS���������������������������������������������������� 6
Summary����������������������������������������������������������������������������������������������� 22
Exercises����������������������������������������������������������������������������������������������� 22
vii
www.allitebooks.com
■ Contents
■
■Chapter 3: Stack Views and the Focus Engine����������������������������� 23
Auto Layout and Stack Views���������������������������������������������������������������� 23
Implementing Stacks���������������������������������������������������������������������������������������������� 23
www.allitebooks.com
■ Contents
Summary��������������������������������������������������������������������������������������������� 103
Exercises��������������������������������������������������������������������������������������������� 103
■
■Chapter 8: CloudKit��������������������������������������������������������������������� 105
Considerations for Using CloudKit������������������������������������������������������� 105
CloudKit Containers����������������������������������������������������������������������������� 105
Database��������������������������������������������������������������������������������������������������������������� 109
Index���������������������������������������������������������������������������������������������� 123
ix
www.allitebooks.com
About the Authors
xi
www.allitebooks.com
■ About the Authors
xii
www.allitebooks.com
Acknowledgments
We would like to thank Apress for all their help in making this book possible. Specifically,
we would like to thank Mark Powers, our coordinating editor, and Michelle Lowman, our
acquisitions editor, for helping us stay focused and overcoming many obstacles. Without
Mark and Michelle, this book would not have been possible.
Special thanks to Jim Markham, our development editor, for all his suggestions
during the editorial review process to help make this a great book. Thanks to Mary
Bearden, the copy editor, who made the book look great.
We would like to thank the CodeRed-I creative design team for their visual design
direction to complete the fresh, stylized front and back cover. Special thanks to Giang Le
for his contemporary and retro graphic design elements.
xiii
Introduction
We are now able to write apps for the new Apple TV. This is great for iOS developers
because everything is very familiar. Xcode, Swift, UIKit Interface Builder and the tvOS
Simulator are very similar to iOS development.
This book assumes you are very familiar with iOS development using Swift. If you
are not, please read our Swift 2 for Absolute Beginners from Apress (www.apress.com/
9781484214893).
Swift 2 for Absolute Beginners takes you through all the development to get you up to
speed to become a tvOS developer and how to do it.
At the end of the webinars, we have a Q&A. You can ask a question on the topic
discussed or on any topic in the book.
Additionally, all these webinars are recorded and available on YouTube. Make sure
you subscribe to the YouTube channel so you are notified when new recordings are
uploaded.
xv
■ Introduction
xvi
Chapter 1
Finally! For years iOS developers have been waiting to write apps for the Apple TV. Three
years ago, we read in Steve Jobs’s biography that Apple had been working on a new Apple
TV, and the current Apple TV was “just a hobby.” In the summer of 2015, Apple finally
announced the new Apple TV along with the operating system called tvOS. Developers
can now write apps for the Apple TV, and there is a new App Store for tvOS apps.
■■Note If you haven’t already read the Introduction to this book, take the time to do so.
The Introduction covers how to access the free tvOS forum, source code used in this book,
free YouTube tvOS training videos, and how to learn Swift 2.
Capabilities
The capabilities of the new Apple TV include:
• 64-bit A8 processor
• 32GB or 64GB of storage
• 2GB of RAM
• 10/100 Mbps Ethernet
• Wi-Fi 802.11a/b/g/n/ac
• 1080p resolution
1
Chapter 1 ■ Getting Started with the New Apple TV
• HDMI
• New Siri Remote/Apple TV Remote
• Bluetooth capability
2
Chapter 1 ■ Getting Started with the New Apple TV
3
Chapter 1 ■ Getting Started with the New Apple TV
4
Chapter 1 ■ Getting Started with the New Apple TV
5
Chapter 1 ■ Getting Started with the New Apple TV
6
Chapter 1 ■ Getting Started with the New Apple TV
Swift Advantages
Swift may not be completely mature yet, but it is ready for prime time. It is a pleasure to
code in Swift and we have noticed about a third of the code you would have to write in
Objective-C is no longer necessary in Swift. For example, Interface Sections are no longer
necessary in Swift.
Swift does fulfill the promise of more efficient and modern development. An entire
class of errors that used to require runtime debugging are now caught by the compiler.
We spend about a quarter of the time debugging Swift apps than we would have with
Objective-C.
www.allitebooks.com
Chapter 1 ■ Getting Started with the New Apple TV
Only one view can be in focus at a time, and only views can receive focus. Consider
the buttons in Figure 1-3.
Button C is currently in focus. Swiping left of the Apple TV remote will focus button B.
Swiping right on the Apple TV remote will focus button D. Swiping left or right more
aggressively will focus button A or button E, respectively.
Apple has updated UIKit and provided implementations for views that can become
focusable by providing a method called canBecomeFocused().
Only the following UIKit classes can become focused:
• UIButton
• UIControl
• UISegmentedControl
• UITabBar
• UITextField
• UISearchBar
Summary
The new Apple TV offers a great opportunity for developers. The tools that are available
in tvOS enable developers to deploy a new generation of apps on a new device in users’
homes.
Exercises
1.
Read the Human Interface Guidelines for tvOS. You can read
the HIG for tvOS at https://developer.apple.com/tvos/
human-interface-guidelines/.
2.
If you haven’t already registered for a developer account, go
register! You can register at https://developer.apple.com.
8
Chapter 2
This chapter will show you the capabilities of the tvOS by walking you through the steps
on how to create a basic tvOS weather app. The app will demonstrate how UIKit controls
look differently on tvOS than they do on iOS and how the development process is nearly
identical. You will use this weather app for both this chapter and Chapter 3. In Chapter 3
you will use Stack Views to lay out part of this weather app.
Building this weather app will also enable you to explore how the focus engine works
and how you can use it in your apps. The goal of the weather app will be to look up the
current weather in different cities using www.OpenWeatherMap.org, a free web service
(see Figure 2-1).
Figure 2-1. The weather app you will develop including UITabBarController,
UITableView, and UIStackViews
The cool thing about tvOS development is how similar it’s to iOS development. Let’s
start building this weather app by choosing a template for the app based on the Tabbed
Application and include a Table View and labels.
9
Chapter 2 ■ The tvOS Weather App
1.
Create a new tvOS Xcode project and select Tabbed
Application. Then click Next (see Figure 2-2).
2.
Name the project (we are using WeatherStation), click next,
and save this to a directory of your choosing, as shown in
Figure 2-3.
10
Chapter 2 ■ The tvOS Weather App
When the project is created, the project settings are displayed, as shown in Figure 2-4.
11
Chapter 2 ■ The tvOS Weather App
When the storyboard file is shown, you can see there are three scenes. The
UITabBarController acts as the entry point to the application and also serves as the
RootViewController that contains the First Scene and Second Scene View Controllers.
■■Note You will frequently need to zoom in and out in the Storyboard to see all the
scenes. Command + and Command – will quickly enable you to zoom in and out.
12
Chapter 2 ■ The tvOS Weather App
Figure 2-6. The WeatherStation app running in the tvOS Simulator with the remote in the
lower right hand corner
You can see that the Tab Bar is at the top of the view in tvOS instead of the bottom of
the view as in iOS apps. Use the remote to switch between tabs and dismiss the Tab Bar by
swiping.
■■Note If you are not able to view the remote, you can access it by going to the
tvOS Simulator menu and selecting Hardware ➤ Show Apple TV Remote or entering
Shift-Command-R.
13
Chapter 2 ■ The tvOS Weather App
6.
Add a Table View to the First Scene and five Labels, as shown
in Figure 2-8.
14
Chapter 2 ■ The tvOS Weather App
■■Note You will need to expand your scene to 100% in Interface Builder to add your Table
View and Labels. Make sure the controls appear under the Document Outline Section in
Interface Builder. (see Figure 2-8).
7.
Add and connect the outlets to the controls, as shown in
Figure 2-9.
8.
Connect the dataSource and delegate outlets for the Table
View, as shown in Figure 2-10.
15
Chapter 2 ■ The tvOS Weather App
Line 18 contains the array of the cities for which you want to display the weather
information.
Lines 30 to 40 contain the data source and delegate functions to populate the
Table View.
Now run the app in the tvOS simulator to see the city names appear in the Table
View. Practice using the remote in the simulator to change the focus in between cities
(see Figure 2-11).
16
Chapter 2 ■ The tvOS Weather App
Figure 2-11. Running the app with the Table View being populated
Now let’s retrieve the weather information from www.OpenWeatherMap.org. Insert the
code as shown in Listing 2-2.
17
www.allitebooks.com
Chapter 2 ■ The tvOS Weather App
58 func setLables(weatherData:NSData) {
59
60 do {
61 let jsonData = try NSJSONSerialization.
JSONObjectWithData(weatherData, options: [])
62 let dataOut = jsonData as! Dictionary<String,AnyObject>
63 if let city = dataOut["name"] as? String {
64 cityNameOutlet.text = city
65 }
66 if let mainDictionary: Dictionary = dataOut["main"] as?
Dictionary<String,AnyObject>{
67 let kelvin = mainDictionary["temp"] as! Double
68 let celsius = kelvin - 273.15
69 let fahrenheit = 9/5 * celsius + 32
70 tempOutlet.text = String(format: "%.f", fahrenheit)
71 }
72
73 if let weatherDict = dataOut["weather"]![0]{
74 weatherOutlet.text = weatherDict["description"] as?
String
75
76 }
77 }
78 catch {
79 print("Fetch failed:")
80 }
81 }
18
Chapter 2 ■ The tvOS Weather App
Figure 2-12. iOS 9 blocking nonsecure (without https://) web service requests
19
Chapter 2 ■ The tvOS Weather App
2.
Add the code in Listing 2-3 to the Info.plist starting at line 31.
The file should then appear as shown in Figure 2-14.
20
Chapter 2 ■ The tvOS Weather App
3.
Close the Info.plist file and open it by clicking it. The Info.plist
should appear as shown in Figure 2-15.
21
Chapter 2 ■ The tvOS Weather App
Now that you have white listed the OpenWeatherMap.org website, you can run the
app and retrieve the weather data for selected cities. Run the app and test the selecting of
cities. The weather data should populate, as shown in Figure 2-16.
Summary
In this chapter you learned how to develop a basic and functional tvOS app. You learned
how to retrieve data from a web service and display it and learned how to white list a
website.
In the next chapter we will use Stack Views layout our labels and explore the tvOS
Focus Engine.
Exercises
1.
Read the OpenWeatherMap.org API JSON format and add the
ability to display humidity, barometric pressure, and wind
direction to the view.
2.
In the Second Scene, display an icon of the current weather
that the selected city is experiencing. For example, if it is
snowing, display a snowflake.
22
Chapter 3
In iOS 9 Apple introduced Stack Views, and these are also available in tvOS. The
UIStackView class provides an interface for laying out collections of views in either a
column or a row. A Stack View lets you utilize Auto Layout, creating user interfaces that
can dynamically adapt to any changes in the available space within your views. In iOS 9
Stack Views automatically adjust for autorotation and screen size.
In this chapter we will expand our WeatherStation app to use Stack Views and also
explore how the tvOS Focus Engine works.
Implementing Stacks
Implementing stacks is pretty easy. The steps below will show how to embed five labels
into a single stack.
1.
Open the WeatherStation app from the previous chapter.
2.
Select the City Name Label.
3.
At the bottom right of Interface Builder, click the Stack icon.
4.
Ensure that the Stack View Axis that Interface Builder selected
is set to “Vertical” as shown in Figure 3-1.
23
Chapter 3 ■ Stack Views and the Focus Engine
Figure 3-1. Placing the City Name label in a Vertical Stack View
5.
Select both Temperature Labels.
6.
At the bottom right of Interface Builder, click the Stack icon.
7.
Ensure that the Stack View Axis that Interface Builder selected
is set to “Horizontal,” as shown in Figure 3-2.
24
Chapter 3 ■ Stack Views and the Focus Engine
You will notice that Interface Builder is smart about choosing the correct Axis
settings when selecting multiple controls.
8.
Select both bottom Weather Labels.
9.
At the bottom right of the Interface Builder, click the Stack
icon.
10.
Ensure that the Stack View Axis that Interface Builder selected
is set to “Horizontal,” as shown in Figure 3-3.
You should see all five labels in three different Stack Views, as shown in Figure 3-4.
25
Chapter 3 ■ Stack Views and the Focus Engine
11.
Now select all three Stack Views and click the Stack icon to
embed these stacks into one stack, as shown in Figure 3-5.
26
Chapter 3 ■ Stack Views and the Focus Engine
Figure 3-5. One Vertical Stack View created from the three Stack Views
■■Note Xcode 7.1.1 Issue: When completing Step 11 above, the labels may not look as
they do in Figure 3-5 and Figure 3-6. Simply select another file and then select the Main.
storyboard file. This will cause Xcode to reset the view correctly.
Ensure the Stack View is a Vertical Axis Stack View. This makes all the views in the
Stack View alignment based vertically to one another.
It appears that all the labels are crunched together. Let’s improve the spacing in the
one Stack View.
12.
Click the parent Stack View, then change the Distribution to
Fill Equally and spacing to 30, as shown in Figure 3-6.
27
Chapter 3 ■ Stack Views and the Focus Engine
13.
To increase the horizontal spacing of the Temp and Weather
labels, select both child Stack Views, change the Distribution
to Fill Equally and Spacing to 30, as shown in Figure 3-7.
Now that you have the one parent Stack View, you can unset the “Extend Edges
Under Top Bars” and Add Missing Constraints in 2 steps. This will enable the First View to
shift automatically scroll up and down when the Tab Bar is visible.
14.
Select the First View Controller and uncheck Extend
Edges – Under Top Bars, as shown in Figure 3-8.
Now we can apply the “Add Missing Constraints” tool to our View Controller and all
our controls will be positioned, as we want in our view.
15.
Add Missing Constraints to the First View Controller, as shown
in Figure 3-9.
28
Chapter 3 ■ Stack Views and the Focus Engine
Congratulations! You did it. Run the app now so you can see how the two constraints
for the Stack View place all five labels where you want them. More importantly, if you add
other controls to the view, you only need to update the constraints for the parent stack,
not all five labels (see Figure 3-10).
29
Chapter 3 ■ Stack Views and the Focus Engine
30
Chapter 3 ■ Stack Views and the Focus Engine
Summary
In this chapter you learned how Stack Views and the focus engine work. Stack Views are
available in iOS and tvOS, but the focus engine is only available in tvOS. The Focus Engine
is available only for tvOS because we can’t tap on our TVs.
Stack Views can save lots of time during the development lifecycle of an app.
Understanding the focus engine will enable you to add to the user’s interface experience
as you create your tvOS applications.
In the next few chapters, we will be exploring some of the more common Apple TV
user interface elements while building a Photo Gallery application.
Exercises
1.
Modify the Stack Views so the Temp and Weather labels are
aligned and laid out more consistently.
2.
Add Constraints within the Stack Views for better readability.
3.
Disable more than one city in the Table View.
4.
Add a button to the First Scene and make the button have
focus when the app starts. The button doesn’t need to do
anything, other than just have focus when the app starts.
31
Chapter 4
For the next few chapters, we will be exploring some of the more common Apple TV user
interface elements while building a Photo Gallery application. Most of the user interface
elements will be familiar to you if you are an experienced iOS developer, but the way
that the user interacts with them is somewhat different since you cannot walk up to your
television and start tapping and swiping on the screen. (Not yet, anyway!)
Figure 4-1. An example of a Page View Controller and its associated Page Control
33
Chapter 4 ■ Creating a Photo Gallery App
From the Page Control near the bottom, you can see that there are five pages in this
Page View Controller, and the user is currently looking at page number three.
For the Photo Gallery app, you are going to create an app consisting primarily of a
Page View Controller that will present the user with a series of full-screen Image View
pages. With each page containing a different photo, this will really take advantage of the
full 1080p high-definition screen available to an Apple TV app.
3.
After clicking Next, enter Photo Gallery for the Product Name
and choose Swift for the Language, as shown in Figure 4-3.
34
Chapter 4 ■ Creating a Photo Gallery App
4.
Click Next again and choose a location (for example, your
Desktop or Documents folder) where you would like to save
the project, then click Create.
You should now be looking at your newly created Photo Gallery project, as shown in
Figure 4-4.
35
Chapter 4 ■ Creating a Photo Gallery App
36
Chapter 4 ■ Creating a Photo Gallery App
2.
Next, you need to select the Main.storyboard file and then
select the View Controller scene as shown in Figure 4-6.
37
Chapter 4 ■ Creating a Photo Gallery App
3.
To delete the scene, either press the Delete key on your
keyboard or choose Edit ➤ Delete from the application menu.
Now that the default View Controller has been removed, it is time to add the Page
View Controller to the project.
3.
Click Next, select UIPageViewController from the Subclass
drop-down list, and enter PageViewController as the Class
name.
4.
Make sure Swift is selected as the Language (as shown in
Figure 4-8), and click Next, followed by Create to add it to the
project.
38
www.allitebooks.com
Chapter 4 ■ Creating a Photo Gallery App
Now that you have added the PageViewController class, you need to add a Page
Content View Controller to the project to handle displaying the pages of images from
within the Page View Controller itself.
1.
Right-click (or Control-click) the Photo Gallery group in the
Project navigator to add another New File to the project,
but this time, select UIViewController from the Subclass
drop-down list and name the class PageContentViewController.
39
Chapter 4 ■ Creating a Photo Gallery App
3.
Select the Page View Controller and choose the Attributes
inspector from the Utilities area and check the Is Initial View
Controller check box (as shown in Figure 4-9) to indicate that
this is the first view controller that will be loaded when the
app is launched.
Figure 4-9. Adding a new Page View Controller to the Main.storyboard and setting it as
the Initial View Controller
■■Note In tvOS, the scenes within a storyboard are large, each the size of a full 1080p
television screen. This can make it difficult to navigate a storyboard containing multiple
scenes. To remedy this, you can zoom in and out of a storyboard by pressing Command +
and Command –, respectively.
4.
Next, select Scroll from the Transition Style drop-down
list instead of Page Curl (as shown in Figure 4-10) to cause
the Page View Controller to show the Page Control with its
horizontal white dots, as shown previously in Figure 4-1.
40
Chapter 4 ■ Creating a Photo Gallery App
5.
Finally, with the Page View Controller scene still selected,
select the Identity inspector in the Utilities area and set the
Class to PageViewController, as shown in Figure 4-11.
Figure 4-11. Setting the Page View Controller scene class to PageViewController
41
Chapter 4 ■ Creating a Photo Gallery App
Now that you have added the Page View Controller scene to the Main.storyboard,
you need to add an additional View Controller for the PageContentViewController class.
1.
Drag and drop a View Controller from the Object library onto
the canvas underneath the Page View Controller scene.
2.
Select the new View Controller and set both the Class
and the Storyboard ID to be PageContentViewController
in the Identity inspector of the Utilities area as shown in
Figure 4-12. (Setting the Storyboard ID of the Page Content
View Controller will allow you to instantiate instances of it
programmatically later on in the chapter.)
Figure 4-12. Setting the Page Content View Controller scene class and Storyboard ID to
PageContentViewController
Now that you have the Page View Controller and Page Content View Controller
scenes added to the Main.storyboard, you need to add the Image View to the Page
Content View Controller to actually display the photos for our Photo Gallery.
■■Note Before adding the Image View to the Page Content View Controller scene, you will
need to zoom back in again to 100% if you have previously zoomed out. The easiest way to
do this is to hold down the Control and Command keys and press =. You can also right-click
(or Control-click) anywhere on the empty blank space of the canvas and choose Zoom to
100%.
42
Chapter 4 ■ Creating a Photo Gallery App
1.
Drag and drop an Image View onto the Page Content View
Controller scene, as shown in Figure 4-13.
Figure 4-13. Adding an Image View to the Page Content View Controller scene
Since you are going to want the Image View to fill the entire screen, you will want
to add some auto layout constraints to the Image View to pin it to the edges of the Page
Content View Controller.
1.
With the Image View selected, click the Pin Tool button in the
layout bar at the bottom of the canvas.
2.
Uncheck the Constrain to margins check box.
3.
Select Items of New Constraints from the Update Frames
drop-down list.
4.
Add the four constraints shown in Figure 4-14.
43
Chapter 4 ■ Creating a Photo Gallery App
Now that the Image View fills the entire Page Content View Controller, the last thing
you need to do is create an outlet for the Image View in the PageContentViewController.
swift file.
1.
Select the Page Content View Controller, and then click the
Assistant editor icon to also open the
PageContentViewController.swift file, as shown in Figure 4-15.
44
Chapter 4 ■ Creating a Photo Gallery App
Figure 4-15. Viewing the Page Content View Controller in the Assistant editor
2.
You may also want to hide the Utilities area temporarily by
clicking the button in the top-right corner of Xcode to give
yourself more room to work.
3.
Zoom the storyboard canvas back to 100% if zoomed out, and
then right-click (or Control-click) and drag from the Image
View to the first line within the PageContentViewController
class definition to add a UIImageView outlet named
imageView, as shown in Figure 4-16.
45
Chapter 4 ■ Creating a Photo Gallery App
Now that the Image View is connected to the imageView outlet, the scene work in
Interface Builder is complete. You can now re-select the Standard editor (by clicking the
icon in the top-right corner of Xcode) and turn your attention to adding the required
data model structures to the project for the Photo Gallery app.
46
Chapter 4 ■ Creating a Photo Gallery App
3.
Select Source under tvOS and then select Swift File.
4.
Click Next and then name the file Photo.swift and then click
Create.
Add the following code into the newly created Photo.swift file:
1 import Foundation
2
3 struct Photo {
4 var name: String = ""
5
6 init(name: String) {
7 self.name = name
8 }
9 }
This Swift Photo structure contains a single property, a String called name (Line 4),
which will store the name of the photo associated with it.
Next, add another Swift File called Album.swift and add to it the code below:
1 import Foundation
2
3 struct Album {
4 var name: String = ""
5 var photos: [Photo] = []
6
7 init(name: String, photoNames: [String]) {
8 self.name = name
9 for photoName in photoNames {
10 self.photos += [Photo(name: photoName)]
11 }
12 }
13 }
The Album structure also contains a String name property (Line 4) as well as an array
of Photo structures called photos (Line 5) that make up the contents of the album.
The Album structure also has a designated initializer (Line 7) that takes in the name
of an album as well as an array of photo name Strings. The array of photo name Strings
is then used to create the photos array of Photo structures when the Album is initialized
(Lines 9-11).
47
Chapter 4 ■ Creating a Photo Gallery App
To add the photo image files to the asset catalog, first download the image files,
as discussed in the Introduction to this book. After they have been downloaded and
unzipped, simply drag and drop the Animals folder into the asset catalog set list, as
shown in Figure 4-18.
48
Chapter 4 ■ Creating a Photo Gallery App
Figure 4-18. Adding the Animals folder of images to the asset catalog
Adding images to an asset catalog automatically copies the images to the project, so
once they have been added, feel free to delete the original files you downloaded.
By default, when images are added to an asset catalog, they are added for All
Universal devices, as shown in Figure 4-19. This means that a single image in an asset
catalog can support multiple files at different resolutions (1x, 2x, 3x) for the various Apple
devices available.
49
Chapter 4 ■ Creating a Photo Gallery App
Figure 4-19. By default, images added to an asset catalog are added for All Universal
devices
You don’t need to support multiple resolutions as you are developing an Apple
TV application, so for each of the images in the Animals folder, check the TV OS Apple
TV check box, uncheck the All Universal check box, and then drag the image from the
Unassigned spot to the 1x Apple TV spot, as shown in Figure 4-20.
50
Chapter 4 ■ Creating a Photo Gallery App
Figure 4-20. Reassigning all of the Universal images to Apple TV images in the asset
catalog
Now that the photo image files have been added to the project, you can start filling
in the details of the PageViewController and PageContentViewController classes. You are
well on our way to finishing up this app!
51
Chapter 4 ■ Creating a Photo Gallery App
Finally, add the following lines to the end of the viewDidLoad method:
This initializes the Image View, loading in the photo represented by the photoName
property that was set by the Page View Controller when it created the Page Content View
Controller.
The final changes you need to make to complete the Photo Gallery app are
within the main PageViewController class. Select the PageViewController.swift
file in the Project navigator and have the PageViewController class adopt the
UIPageViewControllerDataSource protocol by editing the first line of the class definition
to match the following line of code:
Next, add the following properties at the beginning of the class definition:
The pageIndex property (Line 1) keeps track of which page the Page View Controller
is currently displaying, and the album property (Lines 2-4) is the Album structure that
provides the Photos information to the Page Content View Controllers.
Next, add the following lines to the end of the viewDidLoad method:
1 self.dataSource = self
2 if let pageContentViewController =
3 self.pageContentViewController(self.pageIndex) {
4 self.setViewControllers([pageContentViewController],
5 direction: .Forward, animated: true, completion:
6 nil)
7 }
Setting itself as its own data source (Line 1) means that it has adopted the
UIPageViewControllerDataSource protocol, and it will then be able to provide the data
necessary to display the various Page Content View Controller pages. After setting the
data source, you generate the initial Page Content View Controller (Lines 2-3) using
the pageIndex property (which has been initialized to 0), and initialize the Page View
Controller to display the new Page Content View Controller with a Forward navigation
direction (Lines 4-6).
52
Chapter 4 ■ Creating a Photo Gallery App
Now that you have identified the PageViewController as its own data source, you
need to add the following methods required by the UIPageViewControllerDataSource
protocol to the end of the PageViewController class definition:
1 func pageViewController(pageViewController: UIPageViewController,
viewControllerBeforeViewController viewController: UIViewController)
-> UIViewController? {
2 if let contentViewController = viewController as?
PageContentViewController {
3 return self.pageContentViewController(contentViewController.
index - 1)
4 }
5
6 return nil
7 }
8
9 func pageViewController(pageViewController: UIPageViewController,
viewControllerAfterViewController viewController: UIViewController)
-> UIViewController? {
10 if let contentViewController = viewController as?
PageContentViewController {
11 return self.pageContentViewController(contentViewController.
index + 1)
12 }
13
14 return nil
15 }
When the user is swiping back and forth between pages, these two methods are
called to provide the Page View Controller with the page that is before or after the current
page, depending on whether the user has swiped backward or forward, accordingly. If
there is no page before or after the current page (depending on which direction the user
swiped), then the methods simply return nil.
Add the next two methods at the end of the class definition for the two
UIPageViewControllerDataSource protocol methods, which provide the data needed to
display the Page Control:
1 func presentationCountForPageViewController(pageViewController:
UIPageViewController) -> Int {
2 return album.photos.count
3 }
4
5 func presentationIndexForPageViewController(pageViewController:
UIPageViewController) -> Int {
6 return self.pageIndex
7 }
The first returns the total number of pages for the Page View Controller, which in this
case is the number of Photos contained within the Album. The second returns the current
page index so that the Page Control knows which dot should be selected.
53
Chapter 4 ■ Creating a Photo Gallery App
The final method you will add to the end of the class definition is the one that returns
the instantiated Page Content View Controllers for a specified page index:
If an invalid index is passed that is beyond the number of photos within the album,
the method simply returns nil (Line 9). If the index is valid, then the pageIndex property
is updated with the new index (Line 3) and a new Page Content View Controller is
created (Line 2) and initialized (Lines 4-5) with the index and the photo name from the
associated Photo in the Album before it is returned (Line 6).
That’s it! If you run the app by clicking the Build and run button in Xcode, it should
run in the Apple TV simulator and display a full-screen image of a number of cows
grazing, as shown in Figure 4-21.
54
Chapter 4 ■ Creating a Photo Gallery App
Using the Apple TV Remote in the Simulator will allow you to swipe between the
five different photos from the Animals album. Tapping on the left and right sides of the
remote will allow you to scroll through the images as well.
Summary
In this chapter you created a Photo Gallery app to view multiple high-resolution photo
image files using a Page View Controller. This has given you a solid starting point for
learning more about the different User Interface controls available in tvOS.
In the next chapter we are going to expand on the Photo Gallery app by adding the
ability for the user to choose from a list of multiple albums, and then browse the photos
within them. We are also going add a custom static Top Shelf image to further showcase
the contents of the app from the Home screen of the Apple TV.
Exercises
1.
Try changing the Transition Style of the Page View Controller
from Scroll to Page Curl and see what effect that has on the
app. Try slowly swiping back and forth (and even up and
down) to see how the Apple TV responds. Which style do you
prefer?
2.
Try adding some of your own 1080p images to the project to
make your own customized Photo Gallery app.
55
Chapter 5
In Chapter 4, you started the development of a Photo Gallery Apple TV app that used a
Page View Controller to allow the user to browse through a single album of full-screen
photos. In this chapter, we are going to expand on that project by adding the ability for the
user to choose from a list of multiple albums and then browse the photos within them.
We are also going add a custom static Top Shelf image to further showcase the contents of
the app from the Home screen of the Apple TV.
57
Chapter 5 ■ Adding an Album Browser to the Photo Gallery App
58
Chapter 5 ■ Adding an Album Browser to the Photo Gallery App
3.
Click the Next button, select UITableViewController from the
Subclass drop-down list, and enter TableViewController as
the Class name.
4.
Make sure Swift is selected as the Language (as shown in
Figure 5-3), and click Next, followed by Create to add it
to the project.
Now that you have created a TableViewController class, you are going to want to:
1.
Drag and drop a Table View Controller scene onto the
Main.storyboard canvas to the left of the Page View Controller.
2.
With the new Table View Controller scene selected, check the
Is Initial View Controller check box, as shown in Figure 5-4.
59
Chapter 5 ■ Adding an Album Browser to the Photo Gallery App
Figure 5-4. Adding a Table View Controller scene to the Main.storyboard canvas and
making it the Initial View Controller
3.
Next, with the Table View Controller scene still selected, select the
Identity inspector in the Utilities area and change the Class to be
the newly created TableViewController, as shown in Figure 5-5.
Figure 5-5. Setting the Table View Controller scene class to TableViewController
60
Chapter 5 ■ Adding an Album Browser to the Photo Gallery App
Now that the Table View Controller has been added to the project, you need to
configure the Table View Cell to display the appropriate information for each photo album.
1.
First, click the Document Outline button in the
bottom-left corner of the canvas to show the list of scenes in
the Main.storyboard, as shown in Figure 5-6.
Figure 5-6. Viewing the list of Main.storyboard scenes within the Document Outline
2.
Next, expand the Table View item underneath the Table View
Controller Scene by clicking the small gray rectangle next to it,
revealing the Table View Cell, as shown in Figure 5-7.
61
Chapter 5 ■ Adding an Album Browser to the Photo Gallery App
Figure 5-7. Expanding the Table View to reveal the Table View Cell
3.
Select the Table View Cell from within the Document Outline
and then select the Attributes inspector from the Utilities area.
4.
Next, select Subtitle from the Style drop-down list and enter
Cell as the Identifier, as shown in Figure 5-8.
62
Chapter 5 ■ Adding an Album Browser to the Photo Gallery App
The Subtitle style is the default Table View Cell template that provides all of the user
interface elements you need (image, main title, and subtitle) to display the list of photo
albums. The Cell Identifier will be used in the TableViewController class code to identify
which Table View Cell in the Table View Controller scene to use when populating the
Table View. If you had more than one type of Table View Cell in the Table View, you would
just need to give it a different Identifier.
The last thing you need to do in the storyboard is to add a Show segue between the
Table View Cell and the Page View Controller so that when a user selects a particular
photo album from the list they are able to browse through all of the photos within it.
1.
To add the Show segue, first expand the Page View Controller
Scene to reveal the Page View Controller.
2.
Next, right-click (or Control-click) the Table View Cell and
drag it to the Page View Controller, as shown in Figure 5-9.
63
Chapter 5 ■ Adding an Album Browser to the Photo Gallery App
Figure 5-9. Adding a segue between the Table View Cell and the Page View Controller
3.
Release the mouse button and choose Show under Selection
Segue, as shown in Figure 5-10.
64
Chapter 5 ■ Adding an Album Browser to the Photo Gallery App
4.
Select the new Show segue that was added to the Table View
Controller Scene in the Document Outline and change its
Identifier to SelectAlbumSegue in the Attributes inspector, as
shown in Figure 5-11.
That completes all of the changes you need to make to the Main.storyboard, so now
we can turn our attention to writing some code!
65
Chapter 5 ■ Adding an Album Browser to the Photo Gallery App
Add the following code into the newly created Gallery.swift file:
1 import Foundation
2
3 struct Gallery {
4 var albums: [Album] {
5 return [
6 Album(name: "Animals", photoNames: ["Cows", "Dog",
"Horses", "Seagull", "Sheep"]),
7 Album(name: "Cities", photoNames: ["Bridge",
"Fireworks", "Traffic", "Village", "Windows"]),
8 Album(name: "Landscapes", photoNames: ["Coast", "Field",
"Lake", "Lighthouse", "Road"])
9 ]
10 }
11 }
The Swift Gallery structure contains a single computed property, an array of Albums
called albums (Lines 4-10) that consists of three albums, each containing five photos.
66
Chapter 5 ■ Adding an Album Browser to the Photo Gallery App
Figure 5-12. The asset catalog containing the Animals, Cities, and Landscapes photo albums
Adding the gallery property to the Table View Controller will provide it with the
data needed to display the list of photo albums to the user.
2.
Next, scroll down to the numberOfSectionsInTableView
data source method in the TableViewController.swift file and
change the return 0 to return 1, as there is only going to be
one section in this table view that will contain the three rows
of photo albums.
3.
Then, in the numberOfRowsInSection method, change the
return value to the number of albums within the gallery, as
shown below:
1 return self.gallery.albums.count
67
Chapter 5 ■ Adding an Album Browser to the Photo Gallery App
4.
Next, uncomment and edit the cellForRowAtIndexPath
method to match the following:
■■Note If you are wondering why you would remove the last two characters of the names
String (Line 10) before using it, it is because you are creating it by concatenating the name
of each photo, followed by a comma and a space. Since you do not want to have a comma
and a space after the final name, you simply remove those last two characters after exiting
the loop.
After setting the main title and subtitle strings of the cell, the final thing you need to
initialize before returning it is the image, which you do by loading the image associated
with the first photo in the album that is being requested (Line 13).
68
Chapter 5 ■ Adding an Album Browser to the Photo Gallery App
If you build and run the application now, you should see something similar to
Figure 5-13.
Figure 5-13. The Table View Controller showing the list of photo albums
That looks okay, but there is a lot of empty white space underneath the list of three
photo albums. You can fix this issue by making each row taller by adding the following
method to the TableViewController.swift file after the cellForRowAtIndexPath method:
Now when you build and run the application, you should see something similar to
Figure 5-14.
69
Chapter 5 ■ Adding an Album Browser to the Photo Gallery App
Figure 5-14. The Table View Controller showing the list of photo albums with a more
acceptable amount of empty white space
If you select the Animals album using the Apple TV remote, everything works! The
Animals album is displayed, and you can swipe back and forth between the photos within
the album. Pressing the Menu button takes you back to the list of photo albums where
you can swipe down and select either the Cities or Landscapes album and view their
photos as well.
But wait! Selecting either the Cities or Landscapes album still takes us to the Animals
album. Do you know why that is? What have we missed?
The reason that the Page View Controller will only show the Animals album is
because it is still being initialized with that album when it is first created, and you have
not yet implemented the code that passes the album selected from the Table View
Controller on to the Page View Controller.
To do that, you need to uncomment and edit the prepareForSegue method located
at the end of the TableViewController class declaration to contain the following:
70
Chapter 5 ■ Adding an Album Browser to the Photo Gallery App
Remember when you connected the Table View Cell to the Page View Controller
with a Show segue with the SelectAlbumSegue identifier? When a user selects a Table
View Cell, the Show segue is initiated, and the prepareForSegue method is called. In the
method, you first check to see if the segue’s identifier is SelectedAlbumSegue (Line 2). If
it is, you create local references to the Page View Controller and the row that was selected
(Line 3) and initialize the album property of the Page View Controller with the album
from the gallery that is indexed by the selected row (Line 4). That way, when the Page
View Controller is loaded, the album property has already been initialized with the correct
album data.
Great job! You have now completed the Photo Gallery app, giving users the ability to
browse through a list of photo albums to view their associated full-screen photos on their
widescreen HDTV.
71
Chapter 5 ■ Adding an Album Browser to the Photo Gallery App
Selecting the Photo Gallery app next to it shows the default Apple TV Top Shelf
image, as shown in Figure 5-16.
That is not very representative of the Photo Gallery app you have created. Thankfully,
Apple has given developers the ability to add their own customized static Top Shelf
images to their apps, giving them that additional recognition when placed in the top row
of the Home screen.
Adding a custom static Top Shelf image is really quite easy.
1.
Simply click the Assets.xcassets asset catalog in the Project
navigator and expand the App Icon & Top Shelf Image folder.
2.
Then, select Top Shelf Image and drag and drop the
TopShelf.jpg image from the chapter’s downloadable content
to the blank 1x Apple TV space, as shown in Figure 5-17.
72
Chapter 5 ■ Adding an Album Browser to the Photo Gallery App
Now, simply build and run the app, and then press the Menu button on the Apple
TV remote to return to the Home screen. The Top Shelf image should now be displayed
whenever the Photo Gallery app is selected while it is located in the top row of the Home
screen, as shown in Figure 5-18.
Figure 5-18. The Photo Gallery app with its custom static Top Shelf image
73
Chapter 5 ■ Adding an Album Browser to the Photo Gallery App
That looks really great! And it is much more representative of what the Photo Gallery
app has to offer.
Summary
In this chapter you added a Table View Controller to the Photo Gallery app to allow the
user to select from a list of photo albums before viewing the photos using the existing
Page View Controller from Chapter 4. You also added a custom static Top Shelf image to
the app to give the user a better indication as to the contents and functionality of the app
when it is selected from the top row of the Home screen.
In the next chapter, you will customize the Top Shelf even further by adding a
scrollable collection of dynamic thumbnail images for users to choose from when
launching the app.
Exercises
1.
Try adding some additional albums and photos to the app
from an existing album or add new albums to the gallery.
2.
Try adding an additional navigation layer to the app,
perhaps starting with a Table View Controller containing a
list of different galleries. The galleries could contain albums
organized by category, allowing the user to first choose a
gallery before choosing an album to browse its photos.
74
Chapter 6
The Top Shelf area of the Apple TV Home screen is a great place to provide more
information about an app, as well as to showcase what an app has to offer to its users. At
the end Chapter 5, you added a custom static Top Shelf image to the Photo Gallery app. In
this chapter, you are going to customize the Top Shelf even further by adding a scrollable
collection of dynamic thumbnail images for users to choose from, as shown in Figure 6-1.
Figure 6-1. The dynamic Top Shelf of the Photo Gallery app
Users will be able to scroll through the collection of thumbnail images to see a
preview of all of the albums within the app. Selecting any of the thumbnail images will
open the Photo Gallery app, taking the user to the selected full-screen photo.
75
Chapter 6 ■ Adding a Dynamic Top Shelf to the Photo Gallery App
Application Extensions
You will add support for a dynamic Top Shelf by adding a new TV Services application
extension that implements the TVTopShelfProvider protocol to the Photo Gallery app.
App extensions are not apps themselves, but instead allow apps to provide additional
functionality to the rest of the system. Apple Watch apps, custom keyboards, and Today
widgets are some of the other examples of app extensions, specifically for iOS.
1.
To get started, launch Xcode and open the Photo Gallery
project from Chapter 5.
2.
Next, select File ➤ New ➤ Target from the Xcode
application menu.
3.
Select Application Extension under tvOS and choose TV
Services Extension, as shown in Figure 6-2.
4.
Click Next and enter Photo Gallery Extension for the Product
Name, as shown in Figure 6-3.
76
Chapter 6 ■ Adding a Dynamic Top Shelf to the Photo Gallery App
Figure 6-3. Adding the Photo Gallery Extension to the Photo Gallery app
5.
Click Finish and then Activate, if prompted. The Photo Gallery
project should now include the Photo Gallery Extension
target, as shown in Figure 6-4.
Figure 6-4. The Photo Gallery Extension has been added to the Photo Gallery project
77
Chapter 6 ■ Adding a Dynamic Top Shelf to the Photo Gallery App
Figure 6-5. The Build Phases tab selected for the Photo Gallery Extension target
2.
Click the triangle next to the Compile Sources item to expand
it, as shown in Figure 6-6.
78
Chapter 6 ■ Adding a Dynamic Top Shelf to the Photo Gallery App
Figure 6-6. The Compile Sources Build Phase of the Photo Gallery Extension target
3.
Click the + button at the bottom of the Compile Sources list
and add the Gallery.swift, Album.swift, and Photo.swift files,
as shown in Figure 6-7.
Figure 6-7. Adding the Gallery, Album, and Photo classes to the Photo Gallery Extension
79
www.allitebooks.com
Chapter 6 ■ Adding a Dynamic Top Shelf to the Photo Gallery App
Now that the Photo Gallery Extension knows what a Gallery, Album, and Photo
are, you just need to add the actual image files to the target so that they can be used to
generate the thumbnail images.
1.
To add the image files to the Photo Gallery Extension, first
right-click (or Control-click) the Photo Gallery Extension
group, select New Group, and name it Photos.
2.
Download and unzip the associated project files for
this chapter, and drag and drop the Animals, Cities, and
Landscapes folders onto the new Photos group in Xcode.
When prompted, make sure the Copy items if needed check
box is checked, the Create groups radio button is selected,
and the Photo Gallery Extension target check box is checked
before clicking the Finish button, as shown in Figure 6-8.
Figure 6-8. Adding the image files to the Photo Gallery Extension target
■■Note In case you were wondering why the image files were not added to an Asset
Catalog in this instance, it is because the dynamic Top Shelf thumbnail images need to
be initialized using an image file URL. Image file URLs are not available when images are
packaged up in an asset catalog, so that is why you instead add them to the Photo Gallery
Extension target as general bundle resources.
80
Chapter 6 ■ Adding a Dynamic Top Shelf to the Photo Gallery App
81
Chapter 6 ■ Adding a Dynamic Top Shelf to the Photo Gallery App
32 albums.append(albumItem)
33 }
34
35 return albums
36 }
Figure 6-9. The title of the first TVContentItem in the Animals album is Cows
After setting the title, you then set the imageURL (Line 20) to be the location of the
associated image file that you copied to the Photo Gallery Extension earlier in the chapter.
Finally, you set the displayURL (Line 21) to a specially formatted string that will be passed to
the Photo Gallery application to identify which image thumbnail was selected from the Top
Shelf. The displayURL string contains the photogallery scheme (which we will discuss later
in the chapter) as well as the album and photo index values associated with the photo.
82
Chapter 6 ■ Adding a Dynamic Top Shelf to the Photo Gallery App
Once those three properties have been set for the current photo, the TVContentItem
is added to the photos array at the end of the loop (Line 23).
After the photo loop is complete, the photos array contains all of the photo
TVContentItems for the current album. Next, you create a TVContentIdentifier and
TVContentItem for the album, just like you did for each photo (Lines 26-27). Then, you
set the title of the TVContentItem to the album name (Line 29) so it will appear above
each collection of image thumbnails, as shown in Figure 6-9.
After setting the topShelfItems property to be the photos array (Line 30), you add
the completed album TVContentItem to the albums array at the end of the album loop
(Line 32). Once you have added all of the albums to the albums array, the array is returned
(Line 35).
Phew! That was quite a lot of code, but you got through it! Now, if you attempt to
build and run the app extension, you will be presented with the dialog window shown
in Figure 6-10. Because app extensions are not apps that can be run independently, you
need to select Top Shelf from the list to see your changes reflected in the Top Shelf of your
Apple TV.
Figure 6-10. Selecting which app to run with the Photo Gallery Extension
83
Chapter 6 ■ Adding a Dynamic Top Shelf to the Photo Gallery App
After clicking Run, you will see the static Top Shelf image you added in Chapter 5
replaced with the dynamic thumbnails for all of the albums and photos contained within
the gallery. Swiping up on the Apple TV remote when the Photo Gallery app is selected
allows you to focus on the Top Shelf items and swipe back and forth between all of the
available photos.
2.
Once the Info.plist has been selected, hover the mouse
pointer over the last item in the list, click the + button that
appears to add a new key to it, and choose URL types from the
list, as shown in Figure 6-12.
84
Chapter 6 ■ Adding a Dynamic Top Shelf to the Photo Gallery App
3.
After adding the URL types key to the Info.plist, click the
small gray triangle next to it to expand it, revealing the Item
0 subkey.
4.
Then click the small gray triangle next to the Item 0 key to
reveal the URL identifier subkey underneath it.
5.
Click in the Value column of the URL identifier item and
change the value to Photo Gallery URL, as shown in
Figure 6-13.
85
Chapter 6 ■ Adding a Dynamic Top Shelf to the Photo Gallery App
6.
Next, click the + button from within the URL identifier item
and select URL Schemes from the list, as shown in Figure 6-14.
86
Chapter 6 ■ Adding a Dynamic Top Shelf to the Photo Gallery App
7.
Click the gray triangle next to the URL Schemes key to expand
it to reveal its Item 0 subkey. Change the value of Item 0 to be
photogallery, as shown in Figure 6-15.
Adding the photogallery URL Scheme to the Info.plist registers that scheme
(as mentioned earlier in the chapter) with the system. Now, whenever any URL that
begins with photogallery is opened on the Apple TV, it will be opened by the Photo
Gallery app.
Build and run the app extension and select one of the thumbnails from the Top Shelf.
The Photo Gallery app is now launched, but the image that was selected is not yet being
displayed. To accomplish this, you first need to tell the Photo Gallery application how to
handle the URL information that is passed to the app when it is opened from a Top Shelf
thumbnail image.
87
Chapter 6 ■ Adding a Dynamic Top Shelf to the Photo Gallery App
Handling URLs
When an Apple TV app is launched from a matching URL scheme, the URL is passed to a
UIApplicationDelegate protocol method called openURL. Open the AppDelegate.swift file
from the Project navigator and add the follow code to the end of the AppDelegate class
declaration:
In this method, you first use the URL passed in from the Top Shelf TVContentItem
to create an NSURLComponents object (Line 6) in order to extract the albumIndex and
photoIndex values from the URL string (Lines 8-17). Then, if both of those values have
been set (Line 20), you find the TableViewController object from the main app window
(Line 22) and pass it to its viewSelectedTopShelfPhoto method (Line 23).
88
Chapter 6 ■ Adding a Dynamic Top Shelf to the Photo Gallery App
This defines a tuple property containing two integers, one for the album index and
one for the photo index. Initially both of the index values are nil, indicating that a Top
Shelf item has not been selected.
Next, define the viewSelectedTopShelfPhoto method by adding the following code
to the end of the class declaration:
In this method, you first store the album and photo index values within the new
selectedTopShelfItem tuple property (Line 3). Then, you check to see what the current
state of the app’s view controller hierarchy is. If a user has previously left the app viewing
another full-screen image (Line 6), then you would want to dismiss the presented
PageViewController object (Line 7) before viewing the newly selected photo. If there is no
presentedViewController set (Line 9), then that means there is no PageViewController
object to dismiss, so the user can continue to view the selected photo (Line 10).
Next, add the following code to the end of the class declaration to check whether a
Top Shelf item has been selected, and if so, performing the appropriate action:
1 func checkSelectedTopShelfItem() {
2 if let albumIndex = self.selectedTopShelfItem.albumIndex {
3 self.tableView.selectRowAtIndexPath(NSIndexPath(forRow:
albumIndex, inSection: 0), animated: false,
scrollPosition: .None)
4 self.performSegueWithIdentifier("SelectAlbumSegue", sender: nil)
5 }
6 }
89
Chapter 6 ■ Adding a Dynamic Top Shelf to the Photo Gallery App
In this method, if the album index within the selectedTopShelfItem is set (Line 2),
you can then select that row in the table view (Line 3) and manually perform the
SelectAlbumSegue that is used when a user clicks one of the albums from the list to
browse the photos within it (Line 4).
When a user selects a Top Shelf image and the app is opened, depending on its
previous state, a PageViewController object may need to be dismissed. If that is the
case, the app needs to be notified when that process is complete so that it can continue
to view the selected Top Shelf item photo. The easiest way to do this is to override the
Table View Controller’s viewDidAppear method by adding the following code to the
TableViewController.swift file after the viewDidLoad method declaration:
Now, if the segue matches the SelectAlbumSegue identifier (Line 2), after a
Page View Controller is created (Line 3) and its album has been initialized (Line 4),
its pageIndex is set to the photoIndex of the selectedTopShelfItem (Lines 7-8) so
that the appropriate image will be selected once the app is launched. Finally, the
selectedTopShelfItem is reset back to its uninitialized state (Line 9).
90
Chapter 6 ■ Adding a Dynamic Top Shelf to the Photo Gallery App
Now, when you select a thumbnail image from the Top Shelf, the Photo Gallery app
is launched and the appropriate album is displayed with the appropriate photo already
selected.
Summary
Congratulations! Over the course of the past few chapters, you have created a Photo
Gallery app that enables users to select and view photos from within a number of
different photo albums, in addition to viewing those photos when selecting them from
the Top Shelf area of the Apple TV Home screen.
You have learned about using Page View Controllers, Table View Controllers,
and Application Extensions on tvOS, all using Swift. The knowledge you have gained
throughout these chapters will provide you with a great foundation for developing other
apps in the future using these aspects of tvOS development.
In the next chapter, we will explore how to store app information on the Apple TV
itself, as well as how to store and sync data to the cloud.
Exercises
1.
By default, the imageShape property of a TVContentItem is
Square for the default Sectioned TVTopShelfContentStyle.
The other options available are Poster and HDTV. Make the
appropriate changes to the Photo Gallery Extension to utilize
these different styles to see which style you like best.
2.
You can mix and match the TVTopShelfContentStyle values
throughout the TVContentItems displayed in the Top Shelf.
You currently have three albums, and there are three styles
available. Make the appropriate changes to the Photo Gallery
Extension to use a different TVTopShelfContentStyle for each
album, or perhaps choose a random style for each and every
photo to really give your app a unique look!
91
Chapter 7
The Apple TV has undergone quite an evolution when it comes to storage. The original
Apple TV came with a standard 40GB or 160GB hard drive. The Apple TV would use that
storage for holding movies, TV shows, and music locally on the Apple TV. For the next
two generations of the Apple TV, Apple removed the hard drive completely. Instead, the
Apple TV was equipped with 8GB of flash storage. These boxes lacked the ability to locally
store any media; instead movies, TV shows, and music all had to be streamed either from
a local computer or across the Internet. With the fourth-generation, Apple has released a
hybrid solution. The new Apple TVs come in either 32GB or 64GB versions, but apps are
still required to stream most of their data and content. Apple currently limits an app to a
total of 200MB of local storage, but this data are temporary and can be removed when the
app is quit.
This chapter will discuss methods for storing information locally on the Apple TV, as
well as how to sync data using iCloud.
Preferences
There are some things to consider when deciding where to store certain kinds of
information. The easiest way to store information is within the preferences file, but this
method has some downsides.
All of the data are both read and written at the same time. If you are going to be
writing often or writing large amounts of data, this could take time and slow down your
application. As a general rule, your preferences file should never be larger than 100KB.
Currently, the preference file is capped at 500KB for tvOS, but a developer should
consider other storage methods long before reaching that limit.
The preferences file is really nothing more than a standardized file with accompanying
classes and methods to store application-specific information. A preference would be, for
example, the sorting column and direction (ascending/descending) of a list. Anything that
is generally customizable within an app should be stored in its preferences file.
93
Chapter 7 ■ Storing and Sharing Data
Writing Preferences
Apple has provided developers with the NSUserDefaults class; this class makes it easy
to read and write preferences for the iPhone, AppleTV, and Mac OS X. The great thing is
that, in this case, you can use the same code for iOS and Mac OS X. The only difference
between the two implementations is the location of the preferences file.
All you need to do to write preferences is to create an NSUserDefaults object. This is
done with the following code:
This instantiates the prefs object so you can use it to set preference values. Next, you
need to set the preference keys for the values that you want to save. The BookStore app
example will be used to demonstrate specific instructions throughout this chapter. When
running a bookstore, you might want to save a username or password in the preferences.
You also might want to save things such as a default book category or recent searches. The
preferences file is a great place to store this type of information because this is the kind of
information that needs to be read only when the application is launched.
Also, on tvOS, it is often necessary to save your current state. If a person is using your
application presses the home button, you want to be able to bring them back to the exact
place they were in your application when they are done with their phone call.
Once you have instantiated the object, you can just call setObjectforKey to save
your preferences. If you wanted to save the username of sherlock.holmes, you would call
the following line of code:
You can use setInteger, setDouble, setBool, setFloat, and setURL instead of
setObject, depending on the type of information you are storing in the preferences file.
Let’s say you store the number of books a user wants to see in the list. Here is an example
of using setInteger to store this preference:
prefs.setInteger(10, forKey:"booksInList")
After a certain period of time, your app will automatically write changes to the
preferences file.
With just three lines of code, you are able to create a preference object, set two
preference values, and write the preferences file. It is an easy and clean process. Here is
all of the code:
94
Chapter 7 ■ Storing and Sharing Data
Reading Preferences
Reading preferences is similar to writing preferences. Just like with writing, the first step
is to obtain the NSUserDefaults object. This is done in the same way as it was done in the
writing process:
Now that you have the object, you are able to access the preference values that are
set. For writing, you use the setObject syntax; for reading, you use the stringForKey
method. You can use the stringForKey method because the value you put in the
preference was a String. In the writing example, you set preferences for the username
and for the number of books in the list to display. You can read those preferences by using
the following simple lines of code:
Pay close attention to what is happening in each of these lines. You start by declaring
the variable username, which is a string. This variable will be used to store the preference
value of the username you stored in the preferences. Then, you just assign it to the value
of the preference username.
iCloud
The iCloud is a service provided by Apple that allows developers to sync data and
information across multiple devices. This is especially helpful with tvOS apps since the
local storage is limited. In order to implement iCloud storage in an app, a developer must
first make sure that their app has iCloud enabled. To do this, visit the Apple Developer
Portal (http://developer.apple.com). Sign in and click Member Center in the top right
corner of the screen. Then click Certificates, Identifiers & Profiles, as shown in Figure 7-1.
Next, select Identifiers under the iOS section. Then select App IDs from the left-hand
side, as shown in Figure 7-2.
95
Chapter 7 ■ Storing and Sharing Data
Find the App ID in the list and select it. This will bring up a list of the Application
Services available in the app, as shown in Figure 7-3.
96
Chapter 7 ■ Storing and Sharing Data
Click the Edit button at the bottom of the list to add iCloud support. The check boxes
seen in Figure 7-4 allow a developer to enable iCloud. Check the box and the app should
now have access to iCloud.
It is also possible to add iCloud capabilities through Xcode. On the left-hand side,
select your project, then select the active target, and choose the Capabilities tab. You will
then see a screen similar to that shown in Figure 7-5.
97
Chapter 7 ■ Storing and Sharing Data
You can turn iCloud on and off through this method also. Now with iCloud enabled,
it is possible to easily store your data in the cloud.
iCloud KVS
There are two ways to store information in iCloud. One way is to implement iCloud KVS
or key-value storage. The second way is by using CloudKit. CloudKit is more powerful
and more complicated. It will be discussed in Chapter 8. iCloud KVS is very similar to
NSUserDefaults and should only be used for storing very small amounts of data. Apple
caps the iCloud KVS storage at 1MB. The major benefit to using iCloud KVS is that the
data are automatically synced across all iCloud devices within the same account.
The iCloud KVS is implemented very similarly to NSUserDefaults. It has the same
limitations and issues, but is also used in a very similar way. The code to implement
iCloud KVS is fairly simple. Start by creating a new Xcode project. Make sure tvOS
Application is selected. For this project, use Single View Application, as shown in
Figure 7-6.
98
Chapter 7 ■ Storing and Sharing Data
Click Next and enter the name and details of the app. We used the name
iCloudStorage, as shown in Figure 7-7.
99
Chapter 7 ■ Storing and Sharing Data
Once the project save location is selected, Xcode will open the project. Select the
AppDelegate.swift file from the left-hand side of the list of files. We will be implementing
the iCloud KVS in the AppDelegate.swift file.
At the top of the AppDelegate class, under the window variable, you need to add the
following two variables:
100
Chapter 7 ■ Storing and Sharing Data
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "iCloudDataChanged:",
name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification,
object: iCloudKeyStore)
This code tells the notification center to call the method "iCloudDataChanged:"
on your AppDelegate object whenever your key store changes values in any way. Notice
the iCloudKeyStore variable is passed in. It is possible to have multiple key stores and
receive notifications for them separately. Next, you will add the code to check the key
store for the string:
Let’s walk through this code. The name of the key you are using in the
NSUbiquitousKeyValueStore is myString. Obviously, when creating a real app, you will
want to use descriptive titles for your keys such as username or default view. Line 27
attempts to set the value of savedString to the key myString from the key store. If this
succeeds, that means the key exists. You then assign the value of savedString to the
iCloudString variable.
If you are unable to pull myString from the key store, this means the key has yet to
be set in the cloud. You then need to tell the key store to store a value for this key. Line
30 calls the method setString on the key store and passes in a String (Testing) and a key
(myString). Line 31 then tells the key store to sync the data immediately with the cloud.
By default, an NSUbiquitousKeyValueStore will sync its data on a regular basis, but by
calling the synchronize method, you can force the sync immediately.
101
Chapter 7 ■ Storing and Sharing Data
■■Note In this example, you use setString and stringForKey to set and retrieve the
string value from the key store. Apple provides different methods for different data types.
The following retrieval methods are available:
- arrayForKey:
- boolForKey:
- dataForKey:
- dictionaryForKey:
- doubleForKey:
- longLongForKey:
- objectForKey:
- stringForKey:
The AppDelegate.swift file should now look like the one shown in Figure 7-8.
There is still one problem with our code. You have told the NSNotificationCenter to
call the method iCloudDataChanged on your appdelegate, but this method has not yet
been defined. Add the following method to the AppDelegate.swift file:
func iCloudDataChanged() {
if let myString = iCloudKeyStore.stringForKey("myString") {
iCloudString = myString
}
}
102
Chapter 7 ■ Storing and Sharing Data
This method merely assigns the value of myString from the key store to the
iCloudString variable.
You can now compile and run your app.
■■Note You may receive a console message at run time similar to the following error:
This means you have not set up your entitlements for your app correctly.
Summary
In this chapter, you learned how to handle local storage on the Apple TV. You also learned
how to add iCloud storage. We showed you how to become alerted to a change in the
iCloud storage and how to send and receive values to and from it.
Exercises
1.
Add a number to your NSUbiquitousKeyValueStore.
2.
Add an Array to your cloud storage.
103
Chapter 8
CloudKit
Chapter 7 discussed storing preferences both locally on the AppleTV and in the cloud using
NSUserDefaults and NSUbiquitousKeyValueStore. This method works great for storing
small pieces of information, but what happens when the app needs to store a significant
amount of information? What happens when an app needs to search or sort this type of
information? This is where CloudKit comes in. CloudKit is a framework provided by Apple
that allows developers to easily sync databases between different devices.
CloudKit is currently available only for iOS , Mac OS X, and tvOS devices. Apple has
provided CloudKit JS. CloudKit JS looks to enable web apps and any other apps that can
implement javascript to hook into existing CloudKit databases. This chapter will not cover
CloudKit JS since it is not needed on tvOS.
CloudKit Containers
All CloudKit data are separated into different containers. Containers will hold all of the
databases and information for each CloudKit-enabled app. Each app will have its own
container. It is, however, possible to share containers with different apps from the same
developer. The container ID will match the app’s bundle ID. Apple provides a class called
CKContainer for accessing the different containers.
105
Chapter 8 ■ CloudKit
The default app container can be accessed by using the following code:
106
Chapter 8 ■ CloudKit
2.
Click the Add button, as shown in Figure 8-2.
3.
You will then be prompted to enter a description and an
identifier, as shown in Figure 8-3. The description is only used
to display what is stored in the container. The identifier is
necessary for accessing the container.
107
Chapter 8 ■ CloudKit
4.
Enter CloudKit Demo2 for the description and enter a unique
string for the identifier. Identifiers tend to follow the pattern
of iCloud.com.companyID.containerName. The identifier will
be used to access the container in the different apps. Click
Continue and you will see a screen similar to that shown in
Figure 8-4.
108
Chapter 8 ■ CloudKit
Click the Register button and the container is now ready to be used. To access this
container, use the following code:
myContainer = CKContainer.init("iCloud.com.inno.cloudkit2")
Databases
The container ID will need to be replaced with whatever you used to register your
container in the previous step. Each container will contain a public and a private
database. The public database will contain information and assets that are shared among
all of the instances of the database. All users will have read and write access to the public
database through your app.
109
Chapter 8 ■ CloudKit
■■Note A developer needs to be careful when dealing with the public database. If one
user is able to delete items from it, all other users will be affected.
The private database is only accessible to the current user. The user will have to enter
their username and password, but then they will have read and write access to that database.
CloudKit Databases
Apple has provided the CKDatabase class for accessing the databases. Once a container
has been connected, it is easy to access the public and private databases. Use the
following code to access the private database:
Database Records
A CKRecord is used to store data in your database. Each CKRecord has different
pieces of data stored as key-value pairs. Records should be separated into distinct
tables or record types for each type of data. For example, for a bookstore, it would
make sense to have a record type of Book and a separate record type of Author. Each
record type will have a name and fields associated with it. Table 8-1 from Apple’s
documentation (https://developer.apple.com/library/tvos/documentation/
DataManagement/Conceptual/CloudKitQuickStart/CreatingaSchemabySavingRecords/
CreatingaSchemabySavingRecords.html) shows the possible field types for a record.
110
Chapter 8 ■ CloudKit
Creating a record is a fairly easy process. The following code would accomplish this:
This creates a new constant called newBook that is of the type Book. Now, you are
able to set values of fields on this newBook constant:
This code sets the title of the book equal to "The Hobbit". The author of the book
was also set. Now that the CKRecord of the book is all set, it can be saved to the database.
You would save this record to the public database in this case with the following code:
27 CKContainer.defaultContainer().publicCloudDatabase ().saveRecord(newBook,
completionHandler: { (record: CKRecord?, error: NSError?) in
28
29 if error != nil {
30 print("There was an error")
31
32 } else {
33 print("Record Saved Successfully")
34 }
35 })
Line 27 tells the public database of the default container to save this record. It also
passes in a completion handler, which is a method that will run when the first method
is complete. The completion method, in this case, merely tells you if there was an issue
saving the record.
111
Chapter 8 ■ CloudKit
On the next screen, fill in the name of your application. We are using CKBookStore
for the name. The Organization Name and Organization Identifier should already be filled
in. Make sure the language selected is Swift. None of the check boxes need to be checked
(see Figure 8-6). Then click Next.
112
Chapter 8 ■ CloudKit
You will be prompted to save your project. Select a location you can easily access.
Once Xcode opens the project, you will see something similar to Figure 8-7.
113
Chapter 8 ■ CloudKit
By default, the project is selected in the Project Navigator on the left, and the active
target will be selected in the targets list. This allows you to change settings and enable
CloudKit as the active target. Select Capabilities from the Targets menu, as shown in
Figure 8-8.
Expand the arrow next to iCloud. Toggle the switch to On. If your user account
belongs to multiple teams, Xcode will prompt you to select the team to connect with this
application. Make sure CloudKit is checked under the Services heading. Your screen
should now look like Figure 8-9. The Container IDs
114
Chapter 8 ■ CloudKit
For this app, the default container will be used. If additional containers are available
for this app, they will be displayed and are able to be selected on this screen. Apple
also provides a link to the CloudKit Dashboard. This is a web interface Apple provides
developers for administering CloudKit databases. Click the CloudKit Dashboard.
After entering your developer credentials, you should see a screen similar to
Figure 8-10.
115
Chapter 8 ■ CloudKit
You won’t be doing anything in the Dashboard for now, but it is useful for managing
record types, queries, and records. You will be using it later in the chapter.
For now, let’s go back to the app and click the AppDelegate.swift file in the Project
Navigator. You need to add a method to create book records in CloudKit. Under the
import UIKit line, add the following line:
import CloudKit
Now add the following method at the end of the file, but inside the closing brace:
45 func setupBooks() {
46
47 let newBook = CKRecord(recordType: "Books")
48 newBook["title"] = "The Hobbit"
49 newBook["author"] = "J. R. R. Tolkien"
50
51 CKContainer.defaultContainer().publicCloudDatabase.
saveRecord(newBook) { (record: CKRecord?, error: NSError?) ->
Void in
52 print("Done")
53 if(error != nil) {
54 print("error")
55 print(error.debugDescription)
56 }
57 }
58 }
Line 45 creates the method called setupBooks. Line 47 creates a new CKRecord of
the type Book. Lines 48 and 49 add a title and an author to this book. Line 51 is a little
more complicated. It starts by telling the default container to tell its public database to
save this record. You then pass in a block method to be executed when the save is either
completed or fails. You are passing two parameters. The first one is the record you tried to
save and the second one is the error, if any. Line 53 checks to see if there was an error and
displays the information about it.
■■Note If the save function fails, many times it is because the user is not logged into their
iCloud account on the device.
setupBooks()
This will add a book to your cloud every time the app is launched. This is a good way
to test things out, but you will definitely want to change this in the real world. Once done,
your AppDelegate.swift file should look like the one shown in Figure 8-11.
116
Chapter 8 ■ CloudKit
117
Chapter 8 ■ CloudKit
Run your app and see if the record was successfully saved. It should be. Open the
Console log in Xcode to verify the word “Done.” If you do see an error in the log, it is likely
the user will need to log into iCloud on the device.
Now that you have saved this book, you need to work on getting all of the book
records from the cloud. You will retrieve the cloud information in the ViewController.
swift. Click ViewController.swift. Add the import CloudKit line at the top of the file like we
did in the AppDelegate.swift file. In the viewDidLoad method, add the following code to
the bottom of the method:
118
Chapter 8 ■ CloudKit
If you now run this app as it stands, you will receive an error. You now need to go to
the CloudKit Dashboard located at https://icloud.developer.apple.com/dashboard/.
One the left-hand side, click Record Types, then Books, as shown in Figure 8-13.
The number of public records will change depending on the number of times you have
run the app.
119
Chapter 8 ■ CloudKit
Click the downward arrow underneath Metadata Indexes and check the box next to
Record ID, as shown in Figure 8-15. This allows your application to access these metadata
as part of a query. You will notice, Apple will inform you of the cost of selecting that index.
It will add 5% to your storage requirements. This is fine in this case, but when designing
for large CloudKit applications, size will need to be considered.
120
Chapter 8 ■ CloudKit
Now click the Save button at the bottom right corner of the screen. Launch your app
and you should receive a log similar to that shown in Figure 8-16. There will be one line
for each time you called setupBooks().
Summary
In this chapter you learned about CloudKit and the basic objects required to access
CloudKit. You learned about the CloudKit Developer Console and how to view records
and record types in a web browser. You also created an app to save CloudKit records and
retrieve them.
This book as shown you how to begin development for the new AppleTV. We have
shown some of the familiar iOS controls and classes and also highlighted some of the
ones that are different for tvOS. Due to the tvOS lack of local storage, we also spent time
demonstrating how to store and retrieve data from iCloud.
121
Chapter 8 ■ CloudKit
Exercises
1.
Add more books to your cloud storage.
2.
Create a new record type in CloudKit or maybe create an
Author type.
122
Index
A, B
iCloud accounts, 105
NSPredicate, 118
AppDelegate.swift, 88 NSSortDescriptor, 118
Apple TV record ID index, 121
capabilities setupBooks, 116
A8 processor, 3 ViewController.swift, 118
A8 Processor, 3 viewDidLoad, 119
inherited iOS frameworks, 2 CloudKit app
limitations, 5 capabilities, targets menu, 114
Siri Remote, 4 cloudKit dashboard, 115
tvOS project naming, 113
advantages, 6 project screen, 114
Button C, 8 single view tvOS application, 112
focus engine, 7 CloudKit dashboard, 115
swift advantages, 7 CloudKit tvOS app, 111
Swift language, 7
UIKit classes, 8
user interface, 7 D, E
Data storing information
C
BookStore app, 94
classes and methods, 93
CKContainer, 105 iCloud (see iCloud)
CloudKit NSUserDefaults class, 94
app, 115 NSUserDefaults object, 95
AppDelegate.swift file, 116–117 preference values, 94
asset storage and setInteger, 94
data transfer, 105 setObjectforKey, 94
books record type, 119 stringForKey method, 95
CKContainer, 105 tvOS, 94
console log, Xcode, 118 Dynamic top shelf image
containers, 105–110 app extensions, 76–77
dashboard, 115 handling URLs, 88
databases photo gallery extension, 77
CKRecord, 110 TV services extension, 76
completion handler, 111 TVTopShelfProvider protocol (see
newBook, 111 TVTopShelfProvider protocol)
123
■ index
F
Main.storyboard file, 39
PageContentView
Focus engine, 30 Controller class, 42
PageContentView
G, H
Controller.swift file, 44
Page View Controller, 41
Gallery data model structure Transition Style, 40–41
asset catalog, 66–67 Main.storyboard scenes, 61
Gallery.swift file, 66 main title and subtitle strings, 68
Page View Controller, 33–34,
I, J, K, L, M, N, O
38, 63–64, 70–71
PageViewController object, 89–90
iCloud photo albums list, 69
App IDs, 96 photo and album data
capabilities, Xcode, 98 model structures, 46
certifications, prepareForSegue method, 90
identifiers and profiles, 95 project cleanup, 36
enabling, 97 segue identifier, 65
KVS SelectAlbumSegue identifier, 90
AppDelegate.swift file, 100, 102 selectedTopShelfItem, 90
iCloudDataChanged, 102 table view cell, 62, 64, 68, 71
iCloudKeyStore variable, 101 table view controller, 67
new project creation, 99 TableViewController class, 59, 89
NSUbiquitousKeyValueStore, 101 table view controller scene class, 60
NSUserDefaults, 98 TableViewController.swift, 89
savedString, 101 top shelf thumbnail image, 84–87
setString, 101 Photo gallery extension
sync data and information, 95 classes and images adding, 78–80
dynamic Top Shelf data, 78–79
P, Q, R
gallery, album,
and photo classes, 79–80
Photo gallery app TVTopShelfProvider protocol
app completion, 51 implementation, 81–84
asset catalog, 48
cellForRowAtIndexPath method, 68
cities or landscapes album, 70 S
Cocoa touch class, 58 ServiceProvider.swift, 81
creating project, 34 Stack views
custom static auto layout, 23
top shelf image, 71–73 city name label, vertical, 24
detailTextLabel subtitle, 68 horizontal spacing, 28
dynamic top shelf image missing constraints, 29
(see Dynamic top shelf image) temp labels placing, 24
gallery data model structure, 65–66 Uncheck Extend Edges, 28
gallery structure, 67 vertical axis stack view, 27
interface builder vertical spacing, 27
adding constraints, 44 weather App, 29
Image View, 43 weather labels, 25
imageView outlet, 46 WeatherStation app, 23
Initial View Controller, 40 System on a chip (SoC), 3
124
■ Index
T, U, V
control outlets, 15
dataSource and
Table view controllers delegate outlets, 15
Apple’s platforms, 57 labels removing, 14
Main.storyboard canvas, 60 white listing websites, 19
photo albums list, 57, 70 Xcode project and
photo gallery app Tabbed application, 10
(see Photo gallery app) TVTopShelfProvider protocol
TableViewController.swift, 69 dynamic Top
tvOS weather app Shelf data, 81
naming and saving, 11 photo gallery extension, 83
project settings, 11 ServiceProvider.swift, 81
simulator, 12–13 topShelfItems
storyboard file, 12 computed property, 81–82
UIStackViews, 9 TVContentIdentifier, 82
UITabBarController, 9 TVContentItem, 82
UITableView, 9
view design
adding UI Controls, 14 W, X, Y, Z
code implementation, 16 WeatherStation app, 23
125
www.allitebooks.com