41,99 €
Transition to a Professional iOS developer with the most in-depth and advanced level guide on Swift 4 and Xcode 9
This book is for developers who have some experience with iOS programming, but want to take their skills to next level by unlocking the full potential of latest version of iOS with Swift to build great applications.
With good pay for iOS developers, a mature development environment, and Apple users spending more money on the App store than Android users, becoming a professional iOS developer is a great move.
The journey to master iOS development and the new features of iOS 11 is not straightforward, but this book will help you make that transition.
Written for Swift 4 and following the latest Swift API design guidelines, you won't just learn how to program for iOS 11, you'll learn how to write great, readable, and maintainable Swift code that's in line with the industry's best-practices.
The progression of this book reflects the real-world development flow. In the book, you will build real-world applications. You will find a mix of thorough background information and practical examples, so you'll know how to make use of a technique right away while you also get a great understanding of the how and why.
By the end, you will be able to build iOS applications that harness advanced techniques and make the best use of the latest and greatest features available in iOS 11.
This book takes a no-frill approach and is very code-specific. The focus is on teaching advanced concepts through a series of small projects and standalone examples that help you gain expertise with various aspects of iOS application development.
Sie lesen das E-Book in den Legimi-Apps auf:
Seitenzahl: 788
Veröffentlichungsjahr: 2017
BIRMINGHAM - MUMBAI
Copyright © 2017 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing, and its dealers and distributors will be held liable for any damages caused or alleged to be caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
First published: December 2016
Second edition: October 2017
Production reference: 1251017
ISBN 978-1-78839-823-7
www.packtpub.com
Author
Donny Wals
Project Coordinator
Sheejal Shah
Reviewer
Alexandre Freire García
Proofreader
Safis Editing
Acquisition Editor
Nitin Dasan
Indexer
Rekha Nair
Contente Development Editor
Sreeja Nair
Graphics
Jason Monteiro
Technical Editor
Surabhi Kulkarni
Production Coordinator
Melwyn D'sa
Copy Editor
Safis Editing
Donny Wals is a passionate, curious, developer from The Netherlands. Ever since he started his communications and multimedia design studies in Amsterdam, he knew that he didn't just want to build great websites and apps, but also transfer knowledge to his peers and newcomers. He got involved with coaching, mentoring, and assisting in his freshman year.
During his final two years at college, he's been a teacher in web development and spent most of his free time exploring iOS and Objective-C. When Swift was first announced, it didn't take long for him to start playing around with it, and after just a few months of learning and experimenting Donny became the lead iOS developer for the start-up where he'd been working at the time.
As an active member of the iOS-developers Slack community, Donny is always up for helping out people with their code and sharing his own knowledge with his peers.
Alexandre Freire is the reviewer of this book. He is a Spanish iOS developer and the author of several software development courses. At the young age of 26, Alexandre sold his own startup (Apparcar). When he is not coding, you can usually find him supporting Deportivo de A Coruña--his favourite football team--or exploring the most beautiful landscapes of Galicia with his family. You can connect to Alexandre on Twitter at @xandrefreire.
For support files and downloads related to your book, please visit www.PacktPub.com.
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range of free newsletters and receive exclusive discounts and offers on Packt books and eBooks.
https://www.packtpub.com/mapt
Get the most in-demand software skills with Mapt. Mapt gives you full access to all Packt books and video courses, as well as industry-leading tools to help you plan your personal development and advance your career.
Fully searchable across every book published by Packt
Copy and paste, print, and bookmark content
On demand and accessible via a web browser
Thanks for purchasing this Packt book. At Packt, quality is at the heart of our editorial process. To help us improve, please leave us an honest review on this book's Amazon page at https://www.amazon.com/dp/1788398238.
If you'd like to join our team of regular reviewers, you can email us at [email protected]. We award our regular reviewers with free eBooks and videos in exchange for their valuable feedback. Help us be relentless in improving our products!
Customer Feedback
Preface
What this book covers
What you need for this book
Who this book is for
Conventions
Reader feedback
Customer support
Downloading the example code
Downloading the color images of this book
Errata
Piracy
Questions
UITableView Touch Up
Setting up the user interface (UI)
Fetching a user's contacts
Creating a custom UITableViewCell for our contacts
Designing the contact cell
Creating the cell subclass
Displaying the list of contacts
Protocols and delegation
Conforming to the UITableViewDataSource and UITableViewDelegate protocol
Under the hood of UITableView performance
Improving performance with prefetching
UITableViewDelegate and interactions
Responding to cell selection
Implementing cell deletion
Allowing the user to reorder cells
Summary
A Better Layout with UICollectionView
Converting from a UITableView to UICollectionView
Creating and implementing a custom UICollectionViewCell
Understanding the UICollectionViewFlowLayout and its delegate
Creating a custom UICollectionViewLayout
Precalculating the layout
Implementing collectionViewContentSize
Implementing layoutAttributesForElements(_:)
Implementing layoutAttributesForItem(_:)
Implementing shouldInvalidateLayout(_:)
Assigning the custom layout to the collection view
Final words on the custom layout
UICollectionView performance
User interactions with UICollectionView
Cell selection
Cell deletion
Cell reordering
Refactoring the long-press handler
Implementing the reorder method calls
Implementing the data source methods
Adding the edit button
Summary
Creating a Contact Details Page
Universal applications
Implementing navigation with segues
Creating adaptive layouts with Auto Layout
Auto Layout with Interface Builder
Adding a scroll view to make the layout scrollable
Laying out the image and name label
Adjusting the image and name label for large screens
Laying out the bottom section
Adjust the bottom section for small screens
Auto Layout in code
Implementing the compact size layout
Implementing the regular size layout
Easier layouts with UIStackView
Containing labels in a UIStackView
Varying columns and layouts for traits in UIStackView
Passing data between view controllers
Updating the data loading and model
Passing the model to the detail page
Implementing new outlets and display data
Previewing content using 3D Touch
Summary
Immersing Your Users with Animation
Refactoring existing animations with UIViewPropertyAnimator
Understanding and controlling animation progress
Adding vibrancy to animations
Adding dynamism with UIKit Dynamics
Customizing view controller transitions
Implementing a custom modal presentation transition
Making an interactive dismissal transition
Implementing a custom UINavigationController transition
Summary
Improving Your Code with Value Types
Understanding reference types
Understanding value types
Differences between values and references in usage
Memory differences between values and references
Heap allocation
Stack allocation
Using structs to improve your code
Starting your models as structs
Using a struct if you don't need inheritance
Enforcing immutability with structs
Final words on structs
Containing information in enums
Summary
Making Your Code More Flexible with Protocols and Generics
Defining your own protocols
Checking for traits instead of types
Extending your protocols with default behavior
Improving your protocols with associated types
Summary
Refactoring the HelloContacts Application
Properly separating concerns
Extracting the contact-fetching code
Extracting the bounce animation
Adding protocols for clarity
Defining the ViewEffectAnimatorType protocol
Defining a contact display protocol
Summary
Adding Core Data to Your App
Understanding the Core Data stack
Adding Core Data to an application
Modeling data in the model editor
Creating the models
Defining relationships
Creating NSManagedObject subclasses
Summary
Storing and Querying Data in Core Data
Storing data with Core Data
Understanding data persistence
Persisting your models
Refactoring the persistence code
Reading data with a simple fetch request
Filtering data with predicates
Reacting to database changes
Implementing a NSFetchedResultsController
Understanding the use of multiple NSManagedObjectContexts
Summary
Fetching and Displaying Data from the Network
Fetching data from the web
Understanding URLSession basics
Working with JSON in Swift
Updating Core Data objects with fetched data
Implementing the fetch logic
Updating a movie with a popularity rating
Visualizing multiple threads
Wrapping the features up
Adding the rating to the movie cell
Understanding App Transport Security
Observing changes to movie ratings
Summary
Being Proactive with Background Fetch
Understanding how background fetch works
Looking at background fetch from a distance
Looking at background fetch in more depth
Implementing the prerequisites for background fetch
Adding the background fetch capabilities
Asking iOS to wake our app up
Updating movies in the background
Updating the data model
Refactoring the existing code
Updating movies in the background
Preparing the helper struct
Updating the movies
Summary
Enriching Apps with the Camera, Motion, and Location
Accessing and using the camera the simple way
Exploring the AVFoundation framework
Playing audio with AVFoundation
Playing video with AVFoundation
Rendering the camera feed
Understanding the building blocks of a video feed
Implementing the video feed
Implementing CoreMotion
Tracking walks with the pedometer
Reading sensor data with CoreMotion
Creating the login interface
Using CoreLocation to locate your users
Obtaining a user's location
Providing location-based updates with geofencing
Tracking the user's location while they're on the move
Finishing the ArtApp login screen
Summary
Extending the World with ARKit
Understanding how ARKit works
Making sense of the world
Understanding scenes
Rendering a scene
Using ARKit with SceneKit
Using ARKit with SpriteKit
Exploring SpriteKit
Setting up a SpriteKit scene
Implementing an Augmented Reality gallery
Enabling ARKit in an existing project
Summary
Exchanging Data with Drag and Drop
Understanding the drag and drop experience
Understanding UIDragInteractionDelegate
Understanding UIDropInteractionDelegate
Implementing basic drag and drop functionality
Adding drag and drop to a plain UIView
Adding drag and drop to a UICollectionView
Customizing the drag and drop experience
Summary
Making Smarter Apps with CoreML
Understanding what machine learning is
Understanding CoreML
Obtaining CoreML models
Using a CoreML model
Combining CoreML and computer vision
Understanding the Vision framework
Implementing an image classifier
Summary
Increasing Your App's Discoverability with Spotlight and Universal Links
Understanding Spotlight search
Adding your app contents to the Spotlight index
Indexing your app through user activity
Indexing with CSSearchableItem
Containing information in CSSearchableItemAttributeSet
Adding CSSearchableItem instances to the search index
Safely combining indexing methods
Handling searchable item selection
Understanding Spotlight best practices and rating
Adding metadata to your web links
Registering as an indexing delegate
Increasing your app's visibility with Universal Links
Preparing your server for Universal Links
Handling Universal Links in your app
Summary
Instant Information with a Notification Center Widget
Understanding the anatomy of a Today Extension
Understanding app extensions
Understanding Today Extensions
Adding a Today Extension to your app
Discovering your widget
Sharing data with App Groups
Summary
Implementing Rich Notifications
Gaining a deep understanding of notifications
Scheduling and handling notifications
Registering for notifications
Creating notification contents
Creating push notifications
Creating local notifications
Scheduling your notification
Scheduling a timed notification
Scheduling a calendar-based notification
Scheduling a location-based notification
Handling notifications
Handling notifications in your app
Managing pending and delivered notifications
Adding actions to notifications
Implementing Notification Extensions
Adding a Service Extension to your app
Adding a Content Extension to your app
Summary
Extending iMessage
Understanding iMessage apps
Creating an iMessage sticker pack
Optimizing assets for your stickers
Creating a custom sticker app
Implementing custom, interactive iMessage apps
Understanding the iMessage app life cycle
Implementing the custom compact view
Implementing the expanded view
Understanding sessions, messages, and conversations
Composing a message
Sending a message
Summary
Integrating Your App with Siri
Understanding intents and vocabularies
Adding intents to your extension
Adding vocabularies to your app
Adding vocabularies through a .plist file
Teaching Siri vocabularies at runtime
Handling intents in your extension
Resolving the user's input
Confirming the intent status
Performing the desired action
Adding a custom UI to Siri
Summary
Ensuring App Quality with Tests
Testing logic with XCTest
Understanding what it means to test code
Determining what to test
Choosing the correct test type
Unit tests
Integration tests
Isolating tests
Arrange
Act
Assert
Setting up a test suite with XCTest
Optimizing code for testability
Introducing the question loader
Mocking API responses
Using models for consistency
Gaining insights through code coverage.
Testing the user interface with XCUITest
Making your app accessible to your tests
Recording UI tests
Passing launch arguments to your app
Making sure the UI updates as expected
Summary
Discovering Bottlenecks with Instruments
Exploring the Instruments suite
Discovering slow code
Closing memory leaks
Understanding what a memory leak is
Preventing objects from using infinite memory
Avoiding reference cycles
Discovering memory leaks
Summary
Offloading Tasks with Operations and GCD
Writing asynchronous code
Understanding threads
Using dispatch queues in your application
Creating reusable tasks with Operations
Using Operations in your apps
Summary
Wrapping Up the Development Cycle and Submitting to the App Store
Adding your application to iTunes Connect
Packaging and uploading your app for beta testing
Preparing your app for launch
Summary
When Apple launched Swift in 2014, the iOS ecosystem became more accessible than it had ever been for developers. Being able to write apps with Swift's beautiful, readable, and straightforward syntax instead of having to write clunky Objective-C code suddenly enabled a lot of people to play around with iOS development. For me, Swift sparked a renewed interest in developing iOS applications, and the new passion has remained ever since.
This book will hopefully transfer some of that passion to you. This book is written to match my personal preferred way of learning, which is learning by doing. In this book, you'll find examples of applications that you might actually want to build some day. The problems that are tackled in this book are real and practical. This book doesn't cover every single framework that you can use in your apps; there are simply way too many. Instead, the focus is on understanding how you can navigate Apple's documentation, how you can refactor your code, and how you can solve real-world development problems.
If you have tried to build something for iOS before but never really managed to make a full blown app, or if you're looking to expand your knowledge with some iOS-11 specific topics, this book is perfect for you. We'll step beyond the basics and learn everything you need to know to build high-quality applications.
Chapter 1, UITableView Touch Up, is all about table views. Most iOS developers will hVE already seen a table view in their attempts at learning iOS. This chapter is intended as a warm-up for what's to come in the next chapters.
Chapter 2, A Better Layout with UICollectionView, informs that the table view's superpowered sibling is the collection view. This chapter will cover implementing a collection view and writing a custom layout object for it.
Chapter 3, Creating a Contact Details Page, says that if you're building apps, you'll need to make them work on many different screen sizes. This chapter will show you how to use auto layout in order to create beautiful, adaptive layouts.
Chapter 4, Immersing Your Users with Animation, informs that the best apps set themselves apart with beautiful and subtle animations. You'll learn multiple animation techniques, and to top it off, you'll learn how to create custom transitions between view controllers.
Chapter 5, Improving Your Code with Value Types, explains the difference between reference and value types. You'll learn why it's a good idea to use value types as much as possible.
Chapter 6, Making Your Code More Flexible with Protocols and Generics, explains that once you've learned about value types, their possibilities and their limitations, it's only logical to learn about protocol-oriented programming. This style of programming was introduced by Apple and serves as a way to avoid complex inheritance hierarchies and to make code clearer and more testable.
Chapter 7, Refactoring the HelloContacts Application, teaches you to apply the lessons learned from the previous two chapters to improve an app you've already worked on.
Chapter 8, Adding Core Data to Your App, says that many apps have a need to store data into a database. This chapter introduces Apple's CoreData framework as a way to include a database for user data in your app.
Chapter 9, Storing and Querying Data in Core Data, covers how to store data in the database you set up in the previous chapter. We'll also cover querying this data using fetch requests and predicates.
Chapter 10, Fetching and Displaying Data from the Network, showcases how to make use of web APIs to fetch and display data.
Chapter 11, Being Proactive with Background Fetch, teaches that iOS allows apps to refresh and load data in the background. This chapter covers how to do this, and briefly introduces you to dispatch groups.
Chapter 12, Enriching Apps with the Camera, Motion, and Location, shows how to build a login screen for an art app that uses several sensors in the iPhone to create a more immersive experience.
Chapter 13, Extending the World with ARKit, demonstrates how you can use Apple's groundbreaking ARKit framework to build an augmented reality experience.
Chapter 14, Exchanging Data with Drag and Drop, takes you through how to augment an app to allow users to drag contents from your app to other apps and vice versa.
Chapter 15, Making Smarter Apps with CoreML, teaches everything you should know about the CoreML framework. You'll implement a machine learning model that recognizes dominant objects in a scene.
Chapter 16, Increasing Your App's Discoverability with Spotlight and Universal Links, explores how you can make an iOS index for your app's contents to make it available through the powerful Spotlight search index.
Chapter 17, Instant Information with a Notification Center Widget, says that developers can add widgets to the Notification Center to disclose quick information to users; this chapter will teach you how.
Chapter 18, Implementing Rich Notifications, is a walk through everything you need to know about providing a great notification experience for your users. We'll cover both the UI extension and content extension.
Chapter 19, Extending iMessage, shows how to build a sticker app for iMessage or something more complex.
Chapter 20, Integrating Your App with Siri, covers how to integrate the SiriKit APIs in your own applications. This enables you to integrate your app deeply into the iOS platform.
Chapter 21, Ensuring App Quality with Tests, focuses on testing an often overlooked aspect of developing an app. This chapter will teach you how to set up tests for your application.
Chapter 22, Discovering Bottlenecks with Instruments, takes you through how to profile your app's performance with instruments.
Chapter 23, Offloading Tasks with Operations and GCD, informs that apps perform increasingly complex tasks. This chapter teaches you how to ensure that complex or slow tasks don't freeze your user interface.
Chapter 24, Wrapping Up the Development Cycle and Submitting to the App Store, teaches how to distribute your app to beta testers through TestFlight and how to submit your app for review in order to publish it to the App Store.
All the code samples are written in Swift 4.0 with Xcode 9; you'll need a Mac that can run Xcode 9. In order to test all of the code samples in this book, you'll need an iOS device that runs iOS 11 and a payed subscription to Apple's developer program.
This book is for developers who have some experience with iOS and want to take their skills to the next level by unlocking the full potential of the latest version of iOS with Swift for building impressive applications. It is assumed that you have some knowledge of iOS development throughout the book.
Feedback from our readers is always welcome. Let us know what you think about this book-what you liked or disliked. Reader feedback is important for us as it helps us develop titles that you will really get the most out of. To send us general feedback, simply e-mail [email protected], and mention the book's title in the subject of your message. If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, see our author guide at www.packtpub.com/authors.
Now that you are the proud owner of a Packt book, we have a number of things to help you to get the most from your purchase.
You can download the example code files for this book from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you. You can download the code files by following these steps:
Log in or register to our website using your e-mail address and password.
Hover the mouse pointer on the
SUPPORT
tab at the top.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box.
Select the book for which you're looking to download the code files.
Choose from the drop-down menu where you purchased this book from.
Click on
Code Download
.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR / 7-Zip for Windows
Zipeg / iZip / UnRarX for Mac
7-Zip / PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Mastering-iOS-11-Programming. We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
We also provide you with a PDF file that has color images of the screenshots/diagrams used in this book. The color images will help you better understand the changes in the output. You can download this file from https://www.packtpub.com/sites/default/files/downloads/MasteringiOS11Programming_ColorImages.pdf.
Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you find a mistake in one of our books-maybe a mistake in the text or the code-we would be grateful if you could report this to us. By doing so, you can save other readers from frustration and help us improve subsequent versions of this book. If you find any errata, please report them by visiting http://www.packtpub.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details of your errata. Once your errata are verified, your submission will be accepted and the errata will be uploaded to our website or added to any list of existing errata under the Errata section of that title. To view the previously submitted errata, go to https://www.packtpub.com/books/content/support and enter the name of the book in the search field. The required information will appear under the Errata section.
Piracy of copyrighted material on the Internet is an ongoing problem across all media. At Packt, we take the protection of our copyright and licenses very seriously. If you come across any illegal copies of our works in any form on the Internet, please provide us with the location address or website name immediately so that we can pursue a remedy. Please contact us at [email protected] with a link to the suspected pirated material. We appreciate your help in protecting our authors and our ability to bring you valuable content.
If you have a problem with any aspect of this book, you can contact us at [email protected], and we will do our best to address the problem.
Chances are that you have built a simple app before, or maybe you tried but didn't quite succeed. If you have, there's a good probability that you have used UITableView. The UITableView is a core component in many applications on the iOS platform. Virtually all applications that display a list of some sort make use of UITableView.
Because UITableView is such an important component in the world of iOS, I want you to dive in to it straightaway. You may or may not have looked at UITableView before, but that's OK. You'll be up to speed in no time and you'll learn how this component achieves that smooth 60 frames per second scrolling that users know and love. If your app can maintain a steady 60 fps, your app will feel more responsive and scrolling will feel perfectly smooth to users, which is exactly what you want.
In addition to covering the basics of UITableView, like how a UITableView uses a pattern called delegation to obtain information about the contents it should display, you'll learn how to make use of Contacts.framework to build an application that shows a list of your users' contacts. Much like the native Contacts app does on iOS.
UITableView makes use of cells to display its contents. In this chapter, you will create a cell with a custom layout to display the user's contacts. You will learn to do so using Auto Layout. Auto Layout is a technique that will be used throughout this book because it's an important part of every iOS developer's tool belt. If you haven't used Auto Layout before, that's OK. We will start with the basics in this chapter and we'll cover more complex uses of Auto Layout as we go.
To sum it all up, this chapter covers:
Configuring and displaying a
UITableView
Fetching a user's contacts through
Contacts.framework
UITableView
delegate and data source
Creating a custom
UITableViewCell
UITableView
performance characteristics
Every time you start a new project in Xcode, you must pick a template for your application. Each template that Xcode offers provides you with some boilerplate code or sometimes they will configure a very basic layout for you. Throughout this book, the starting point will always be the Single View Application template. This template provides you with a bare minimum of boilerplate code. This enables you to start from scratch every time, and it will boost your knowledge of how the provided templates work internally.
In this chapter, you'll create an app called HelloContacts. This is the app that will render your user's contacts in a UITableView. Create a new project by selecting File -> New -> Project. Select the Single View Application template, give your project a name (HelloContacts), and make sure you select Swift as the language for your project. You can uncheck all Core Data- and testing-related checkboxes; they aren't of any use to this project. Your configuration should resemble the following screenshot:
Once you have your app configured, open the Main.storyboard file. This is where you will create your UITableView and create its layout. Storyboards are a great way for you to work on an app and have all the screens in your app visualized at once.
If you have worked with UITableView before, you may have used UITableViewController. This is a subclass of UIViewController that has a UITableView set as its view. It also abstracts away some of the more complex concepts of UITableView that are key to understand for any experienced iOS developer. So, for now, you will be working with the UIViewController subclass that holds UITableView and is configured manually.
On the right-hand side of the window, you'll find the Object Library. The Object Library is opened by clicking on the circular icon that contains a square in the bottom half of the sidebar. In the Object Library, look for a UITableView. The following screenshot shows the Object Library:
If you begin typing the name of the component you're looking for in the search box, it should automatically be filtered out for you. After you locate it, drag it into your app's view. Then, with UITableView selected, drag the white squares to all corners of the screen so that it covers your entire viewport.
If you go to the dynamic viewport inspector at the bottom of the screen by clicking on the current device name as shown in the following figure and select a larger device such as an iPad or a smaller device such as the iPhone SE, you will notice that UITableView doesn't cover the viewport as nicely. On smaller screens, the UITableView will be larger than the viewport. On larger screens, UITableView simply doesn't stretch.
To achieve a more flexible layout that does scale, we must use Auto Layout. Auto Layout enables you to create layouts that will adapt to different viewports to make sure it looks good on all devices that are currently out there. For UITableView, you can pin the edges of the table to the edges of the superview, which is the view controller's main view. This will make sure the table stretches or shrinks to always fill the screen.
Auto Layout uses constraints to describe layouts. UITableView should get some constraints that describe its relation to the edges of your view controller. The easiest way to add these constraints is to let Xcode handle it for you. To do this, switch the dynamic viewport inspector back to the view you initially selected.
First, ensure that your UITableView properly covers the entire viewport, and then click on the Resolve Auto Layout Issues button at the bottom-right corner of the screen and select Reset to Suggested Constraints.
This button automatically adds the required constraints for you. The added constraints will ensure that each edge of UITableView sticks to the corresponding edge of its superview. You can manually inspect these constraints in the Document Outline on the left-hand side of the Interface Builder window.
Each constraint describes how the table view should behave in relation to other views on the screen. The added constraints in this case describe how each edge of the table should be equal to each edge of its super view, which covers the entire screen.
Make sure that everything works by changing the preview device in the dynamic viewport inspector again. You should be able to verify that no matter which device you choose now, the table will stretch or shrink to always cover the entire view.
Now that you have set up your project with a UITableView added to the view and the constraints required to make the UITableView cover the entire screen have been added, it's time to start writing some code. The next step is to use Contacts.framework to fetch some contacts from your user's address book.
To display contacts in your UITableView, you will must set up a few more things. First and foremost, you'll need to create a UITableViewCell that displays contact information. To do this, you'll create a custom cell by creating a subclass of UITableViewCell. The design for this cell will be created in Interface Builder. To make the views added to the cell in Interface Builder available to our code, @IBOutlets are added to the UITableViewCell subclass. These @IBOutlets are the connections between the visual layout in Interface Builder and your code.
The first thing you need to do is drag a UITableViewCell out from the Object Library and drop it on top of the UITableView. This will add the cell as a prototype cell. The design you create in this cell will be replicated in all other cells that are added to the UITableView through code.
Next, drag out a UILabel and a UIImageView from the Object Library to the newly added UITableViewCell, and arrange them as they are arranged in the following screenshot. After you've done this, select both the UILabel and UIImage and use the Reset to Suggested Constraints option you used earlier to lay out the UITableView. If you have both the views selected, you should see the same blue lines that are visible in the following screenshot:
These blue lines represent the constraints that were added to lay out your label and image. You can see a constraint that offsets the label from the left side of the cell. Between the label and the image, a constraint is shown that spaces these two views. The horizontal line through the middle of the cell is a constraint that vertically centers the label and image inside of the cell. You can inspect these constraints in detail in the Document Outline on the right. Now that our cell is designed, it's time to create a custom subclass for it and hook up @IBOutlets.
To get started, create a new file (File | New | File...) and select a Cocoa Touch file. Name the file ContactTableViewCell and make sure it subclasses UITableViewCell, as shown in the following screenshot:
When you open the newly created file, you'll see two methods already added to the template for ContactTableViewCell.swift. These methods are awakeFromNib and setSelected(_:animated:). The awakeFromNib method is called the very first time this cell is created; you can use this method to do some initial setup that's required to be executed only once for your cell.
The other method is used to customize your cell when a user taps on it. You could, for instance, change the background color or text color or even perform an animation. For now, you can delete both of these methods and replace the contents of this class with the following code:
@IBOutlet var nameLabel: UILabel! @IBOutlet var contactImage: UIImageView!
The preceding code should be the entire body of the ContactTableViewCell class. It creates two @IBOutlets that will allow you to connect your prototype cell with them so that you can use them in your code to display the contact's name and image later.
In the Main.storyboard file, you should select your cell, and in the Identity Inspector on the right, set its class to ContactTableViewCell (as shown in the following screenshot). This will make sure that the Interface Builder knows which class it should use for this cell, and it will make the @IBOutlets visible to Interface Builder.
Now that the prototype cell has the correct class, select the label that will hold the contact's name in your prototype cell and click on Connections Inspector. Then, drag a new referencing outlet from the Connections Inspector to your cell and select nameLabel to connect the UILabel in the prototype cell to the @IBOutlet that was added to the UITableViewCell subclass earlier (refer to the following screenshot). Perform the same steps for the UIImageView and select the contactImage option instead of nameLabel.
The last thing you will need to do is to provide a reuse identifier for the cell. The reuse identifier is the identifier that is used to inform the UITableView about which cell it should create or reuse when needed. Cell reuse is an optimization feature that will be covered more in depth later in this chapter.
To set the reuse identifier you must open the Attributes Inspector after selecting your cell. In the Attributes Inspector, you will find an input field for the Identifier. Set this input field to ContactTableViewCell.
Now that the custom UITableViewCell is all set up, you need to make sure that the UITableView is aware of the fact that our ViewController class will provide it with the required data and cells by setting the delegate and data source properties.
One easily overlooked fact about UITableView is that no matter how simple it might seem to use in your apps it's a pretty complex component. By not using a UITableViewController, we expose some of this complexity. You already had to manually set up Auto Layout constraints so the list always covers the full view. Then, you had to manually create and configure a prototype cell that's used to display data.
The next step in implementing the list of contacts is to provide the UITableView with information about the contents we want it to display. In order to do so, you'll implement the data source and delegate for your UITableView. These properties make use of some advanced concepts that you're likely to have seen before, but you have probably never been aware of what they are and how they work. Let's change that right now.
Throughout the iOS SDK and the Foundation framework, a design pattern named the delegation pattern is used. The delegation pattern enables one object to perform actions on behalf of another object. When implemented correctly, this patterns allows you to separate the concerns between different objects and decouple them. The following figure shows how the delegation pattern for a UITableView component and its UITableViewDataSource works:
The UITableView makes use of two delegates in order to render a list. One is called the delegate, the other is called the data source. Whenever you use a UITableView, you must explicitly configure the data source and delegate properties. At runtime, the UITableView will call methods on its delegate and data source in order to obtain information about cells, handle interactions, and more.
If you look at the documentation for the UITableView's delegate property you'll find out that its type is UITableViewDelegate?. There are two things that we learn from this type. First, it tells you that any object that wants to act as the UITableView's delegate must conform to the UITableViewDelegate protocol. Second, the question mark tells you that the delegate is an Optional property. The question mark after the type is what gives this away. An Optional property can either have a value of the specified type (UITableViewDelegate in this case) or nil. The UITableView's delegate must be Optional because it's not strictly required to set it; you can create an instance of UITableView without ever setting the delegate property.
A protocol, like UITableViewDelegate, provides a set of properties and/or methods that any object that conforms to (or adopts) this protocol must implement. In some cases all of these properties and methods are required; the compiler will throw an error if a method specified by the protocol is not implemented. In other cases, there might be methods that are optional; you don't have to implement these in order to conform to the protocol. An example of a protocol with optional methods is UITableViewDelegate. You can conform to this protocol without implementing any extra methods.
When implementing a UITableView's data source, you'll find that the UITableViewDataSource protocol has a couple of mandatory methods to ensure that a data source is able to provide UITableView with the minimum amount of information needed in order to render the cells you want to display.
If you've never heard of delegation and protocols before, you might feel like this is all a bit foreign and complex. That's OK; throughout this book you'll gain a deeper understanding of protocols and how they work. You'll even learn a thing or two about a special programming paradigm called protocol-oriented programming. For now, it's important to be aware that a UITableView always asks another object for data through the UITableViewDataSource protocol and that interactions are handled though the UITableViewDelegate.
When you take a closer look at UITableView and the steps involved in displaying a list of contents you'd find the following steps:
UITableView
needs to reload the data.
UITableView
checks whether it has a
dataSource
and asks it for the number of sections in the list.
Once the
dataSource
responds with the number of sections, the table view will figure out how many cells are required for each section. This is done by asking the
dataSource
for the number of cells in each section.
Now that the cell knows the amount of content it needs to render, it will ask its
dataSource
for the cells that it should display.
Once the
dataSource
provides the required cells based on the number of contacts, the
UITableView
will request that it displays the cells one by one.
This process is a good example of how UITableView uses other objects to provide data on its behalf. Now that you have a good understanding of how delegation works for UITableView, it's about time you start implementing this in your own app.
Earlier in this chapter you briefly read about the cell reuse in UITableView. You had to assign a reuse identifier to your UITableViewCell so the UITableView knows which cell you want to use. This is done so UITableView can reuse existing cells. This means that UITableView only needs to hold the visible cells and a few offscreen cells in memory instead of all of the cells you might want to show, even if the cell is off screen. Refer to the following figure for a visualization of what this looks like:
You can see that there are only a couple more cells in memory, or rendered, than there are visible cells. The UITableView
