Streaming is available in most browsers,
and in the Developer app.
-
Discover search suggestions for Apple TV
Searching your tvOS app just got even better. Get ready to explore the new simplified search interface and learn how to integrate it into your app with UISearchController. Support your global audience with the addition of new international keyboards and languages. Discover how to add search suggestions to your interface and update results with suggestions on the fly. And we'll share some of our favorite tips for adding a great search experience to Apple TV.
Resources
-
Download
Hello and welcome to WWDC. Hi my name is Dale Taylor and I'm an engineer on the tvOS team. Today I'm going to talk to you about Search. In tvOS 14, we've made it even better. Here's how search looks in our TV app. We've increased the size of the text in the search field, so it's easy to see what you've typed. And in many languages we've optimized the keyboard layout to one line. That leaves more space for your search results. Some apps like our Music app take advantage of our new search suggestions feature. These suggestions allow you to minimize typing and find what you're looking for even faster. If you're already using UISearchController, you get most of what you've seen here for free. For those of you that aren't, let's review how simple it is to add to your app. Let me show you. We have a simple tab-based app here with photos and videos from travel over the years. As a reminder, tvOS apps work best with a NavigationController as the root view controller that contains a UITabBarController. Let's head to Xcode and look at adding search UI to our app.
First let's add a new view controller to go in our tab bar. We can call it SearchViewController. Then we'll set up some basic functionality.
We can configure a tab bar item. We'll use the search system item because that's the platform convention for indicating a search tab. Now let's add our SearchController. Since we're adding this is a child ViewController, we want to put this in a UI search container view controller. First let's set up some constants to hold our variables. Then we can create instances of our SearchController and SearchContainerViewController. We want to add that as a child view controller as well and viewDidLoad.
To show our search results we'll need a search results controller. We have one already made named GridViewController with a simple collection view and an 'items' property. Anything we set on the items property will show up in our collection view. Let's start by defining a constant.
Then we can create an instance of this view controller and pass it to our UISearchController.
We'll also want our search controller to scroll along with our collection view, when we scroll through the search results. searchControllerObservedScrollView in viewDidLoad. We'll want to update the contents of the results of view controller when our search results change. Let's start by making our view controller conform to UISearchResultsUpdating.
Then we can set ourselves as the searchResultsUpdater in viewDidLoad. Then we can handle updates from our search controller and updateSearchResults.
We can filter out the data and we can set those results on our search results controller. Finally, we can go to our app delegate and we can add our new view controller to our tab bar. Let's give it a try. If I swipe over to search you can see what we built. If we try searching now, we can see it filter our search results. Now let's talk about what we can do to make it even better. You may remember that I mentioned search suggestions earlier. Before I show you how easy they are to implement in our sample app, let me tell you a little bit about how to use them. We've added a new class UISearchSuggestionItem. It's a model that represents the search suggestion in the UI. It supports an image, text and a description for accessibility. To display these you just assign them to the new searchSuggestions property on your UISearchController. If you have your own object, feel free to use that as well, as long as it conforms to the UISearchSuggestion protocol. Here's an example of how you'd use it. You can just create UISearchSuggestionItems with the optional properties, and assign an array of suggestions to the search controller. Now that you know how to add search suggestions to your search controller, how do you make them update dynamically? You'll use the UISearchResultsUpdating protocol that I mentioned earlier in the demo. You'll recall that this gets assigned to the searchResultsUpdater property on UISearchController. In the demo we used this protocol to handle text input updates with updateSearchResultsForSearchController. We used the search term from the search bar to query our data source. We've extended this protocol in tvOS14 to handle search suggestions. When someone using the app selects a search suggestion, you can respond to it in updateSearchResultsForSearchController:sel ectingSearchSuggestion: This is useful because the search suggestion can contain more information than just the search term. For instance, you could use the suggestion's image to differentiate between content types. Now that I've given you a brief overview of how search suggestions work, let me show you how to add them to our sample project where we integrated search. Our datasource has the capability of giving us suggested search results. Let's start by making our SuggestedEntry conform to UISearchSuggestion.
We can define properties for the localizedSuggestion an iconImage. And we'll fill out a description for accessibility as well.
You'll notice that for our icon image. We're returning a different image whether it's a video or photo - that way we can see that in our suggestion when it's on screen. Now we can go back to our searchController and display these suggestions in our search UI. All we have to do is assign them to the searchSuggestions property when the input changes. We can fill in our empty parameter for suggestions, and then we can assign the suggestions to our searchController.
If no one's typed anything, we don't need any suggestions, so we'll assign an empty array.
Now let's run our app and see how it looks.
If we navigate over to the search tab and start typing, we can see the suggestions populate as we type. Let's see what happens if I click on a suggestion. Hmm. I clicked on the suggestion for videos named blue, so I shouldn't have any photos in my search results. No problem, that's an easy fix. Let's head back to our searchController. We can adopt the new method in UISearchResultsUpdating to handle the SearchSuggestion being selected.
Then we can check to see if our suggestion was for a video suggestion.
If it was, we'll update our search results accordingly.
We can navigate back to the search tab, start typing blue and select our suggestion for blue video. You'll notice that now we only see videos when selecting that suggestion. That's exactly what we wanted. We've worked hard to make UISearchController as easy to use as possible, but here are a few suggestions to help make sure people using your app have the best experience. Our keyboard is highly adaptable to various languages and input methods. You should consider this when laying out your search results. Here are a few examples of alternate layouts. For people using IR remotes, we'll display a grid keyboard. While typing, the search results will only occupy some of the screen width, and then they'll slide in to fill the screen when focused. When the system language is set to Thai, we use a three line keyboard layout to provide the best input experience. Keep this in mind when sizing search results because not as many will fit on-screen. You should also try to avoid covering the keyboard with your own UI, even in the borders outside the safe area. It will likely lead to focus issues and we don't recommend doing it. If you need to differentiate between types of content in search suggestion items, use symbol images. It's a great way to present more information in limited space. Our library of SF symbols will work great for these suggestions. Today we've shown you the improvements we've made to UISearchController in tvOS 14 and how easy it is to adopt. You saw how you can integrate search suggestions to make searching even faster. If you follow the best practices we've shown you here, your customers will have a great search experience in your app. Thanks and enjoy the rest of the conference.
-
-
1:40 - SearchViewController init
private let appData: AppData init(appData: AppData) { self.appData = appData super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
-
1:51 - Search Tab Bar Item
// use the system standard search tab bar item tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarItem.SystemItem.search, tag: 0)
-
2:05 - SearchController and SearchContainerViewController Definition
private let searchController: UISearchController private let searchContainerViewController: UISearchContainerViewController
-
2:11 - SearchController and SearchContainerViewController Initialization
self.searchController = UISearchController(searchResultsController: self.searchResultsController) self.searchContainerViewController = UISearchContainerViewController(searchController: searchController)
-
2:16 - viewDidLoad - Add Child View Controller
override func viewDidLoad() { addChild(searchContainerViewController) searchContainerViewController.view.frame = view.bounds view.addSubview(searchContainerViewController.view) searchContainerViewController.didMove(toParent: self) }
-
3:17 - Set searchControllerObservedScrollView
// scroll search controller allong with results collection view searchController.searchControllerObservedScrollView = searchResultsController.collectionView
-
3:43 - Assign searchResultsUpdater
searchController.searchResultsUpdater = self
-
4:00 - Implement updateSearchResults
func updateSearchResults(for searchController: UISearchController) { if let searchText = searchController.searchBar.text { // get search results for 'searchText' from data source let (results, _) = appData.searchResults(seachTerm: searchText, includePhotos: true, includeVideos: true) searchResultsController.items = results } else { // no search text, show unfiltered results searchResultsController.items = appData.allEntries } }
-
4:16 - Create Instance of SearchViewController
let searchViewController = SearchViewController(appData: appData)
-
5:30 - UISearchSuggestionItem Example
let suggestion1 = UISearchSuggestionItem(localizedSuggestion: "Result1", localizedDescription: "Result1", iconImage: nil) let suggestion2 = UISearchSuggestionItem(localizedSuggestion: "Result2", localizedDescription: "Result2", iconImage: nil) searchController.searchSuggestions = [suggestion1, suggestion 2]
-
7:05 - Implement UISearchSuggestion Properties
var localizedSuggestion: String? { return self.name } var iconImage: UIImage? { return self.isVideo ? UIImage(systemName: "video") : UIImage(systemName: "photo") }
-
7:20 - Implement Accessibility Description
var localizedDescription: String? { if (self.isVideo) { return String.localizedStringWithFormat(NSLocalizedString("%@ - Video", comment: ""), self.name) } return String.localizedStringWithFormat(NSLocalizedString("%@ - Photo", comment: ""), self.name) }
-
9:01 - Add new UISearchResultsUpdating
func updateSearchResults(for searchController: UISearchController, selecting searchSuggestion: UISearchSuggestion) { if let searchText = searchController.searchBar.text { var includePhotos = true; var includeVideos = true; } }
-
9:13 - Inspect Suggestion
// check if the suggestion is for a photo or video if let suggestedEntry = searchSuggestion as? SuggestedEntry { includeVideos = suggestedEntry.isVideo includePhotos = !includeVideos }
-
9:21 - Filter Results
// filter the results by to include photos, videos, or both let (results, _) = appData.searchResults(seachTerm: searchText, includePhotos: includePhotos, includeVideos: includeVideos) searchResultsController.items = results
-
-
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.