Catalog view is currently a beta feature of LayoutTest that can help you to see all of the different versions of your view that exist with different data at a glance. This can be really helpful to help a designer see what different things can happen to the view with the layout she/he has defined. You will explore this feature and see how it may be helful for your in your iOS development adventures.
- [Instructor] Layout Test has a beta feature called catalog view. It allows you to quickly make a sample app that shows your view with all combinations of data. This can be very useful when working with a designer to show how the design responds to different edge cases. Let's take a look at how to use this feature. Let's open up the Xcode Workspace. As you see, it has the same name as a previous project. Now, what we're going to need to do is to create a new app target for this new application. This application is going to be the catalog sample.
We need a new app target because we don't want to use our standard actual app target because it's not going to be part of the app we're making. Also, this uses internal APIs and cannot be released in production in the App Store. To do this, we're going to click the project on the left. We're going to click the dropdown here and hit Add Target. We're going to scroll down under iOS to Single View Application, hit Next.
We're going to call this UsingTestDataCatalog. We don't need unit tests for this one because it's just the catalog app. It's under the UsingTestData project. Let's hit Finish, and we're done. Now, you'll see on the left here we have UsingTestDataCatalog folder and a whole other application here. We're also going to make a quick change here and take out the main storyboard from the main interface. This way, it won't automatically launch the storyboard because we're going to change that later.
Now, we need our view to test. That view, EntityRowView, is in the UsingTestData target, so we need this to be available in our UsingTestDataCatalog target as well. To do this, we can go on the right to the document inspector, scroll down, and under Target Membership, we're going to check the box next to UsingTestDataCatalog. We're going to do this for the .swift file as well. So now we have the EntityRowView.swift and zip files usable in the UsingTestDataCatalog.
Also, since we have images in the assets here, we're going to use the same assets as well. Let's do the same thing. Target Membership, and let's delete the one that's there already, 'cause we're not going to need that. Now, the UsingTestDataCatalog is going to need a dependency on layout tests as well to be able to make this catalog view. We're going to go to the terminal. In order to do this, we're going to need to go to the right folder. What we can do is type cd, space, go to the Finder.
Here's the folder right here. We can actually click, hold, and drag the icon right here into the terminal, and it will put the path there. Now we just hit the return or enter key, and we're there. Now, let's edit the Podfile. Vim Podfile. What we're going to do is we're going to make a new target, and we called it UsingTestDataCatalog, and for this, we're going to do LayoutTestBase.
LayoutTest includes all of the testing framework, but LayoutTestBase has the catalog in it. This is very important. We save this and quit, and now we should be set up. We can do pod install, and now, our dependencies are correct. If we go back to Xcode, we now have access to it. Now we need to implement a protocol called ViewCatalogProvider for our view. So what we're going to do is we're going to create an EntityRowView+LayoutTest in the TestDataCatalog target.
So we're going to click on that, Command + N to make a new file. We'll just do a standard .swift file, call it EntityRowView+LayoutTest. Make sure it's in the correct target, hit Create, and we're good to go. Now, in here, we're going to need to make sure to import LayoutTestBase. In order for that to show up, we're going to change our target to the catalog and build this.
Now our autocomplete should work well. The ViewCatalogProvider protocol actually implements the ViewProvider protocol, so it's going to be very similar to what we did before. We're going to make an extension on EntityRowView that implements the ViewCatalogProvider protocol. To make this easier, we're going to grab the code from the EntityRowView+LayoutTest from the LayoutTest one and just bring that over.
But we're not going to need sizesForView, because it's going to go on one simulator. So, let's select all of this, copy it, Command + C, come to our new file, and paste. So this will provide the data and the view for the catalog. Next, we need to implement the method specific to the catalog view itself. These are as follows: the reuseIdentifier, because we're making a UITableView.
Remember to make that public. The registerClass method, on tableView. The heightForTableViewCellForCatalog fromData method. And if your view is already a UITableViewCell, you don't need to do anything else, but if your view is not, you need to do this method as well. tableViewcellForCatalog, where you create a cell to be used. Now, since our EntityRowView is a UIView and not a UITableViewCell, we're going to need to create a UITableViewCell subclass to be able to show this view.
I've already done this in a separate file, so we're going to drag this into our project. Let's go to the Finder, and in the folder for the exercise files, you'll see an EntityRowViewCell. If we drag this in into the UsingTestDataCatalog target, and we hit Finish, we now have access to it. Let's take a look at this file. We have a standard EntityRowViewCell, which is a UITableViewCell subclass. We have a constant for the reuseIdentifier. We have a property for the EntityRowView itself.
We have a setup method that takes in data that we will pass, and we'll actually set up the EntityRowView using our view forData method that we already implemented. Then, we add it to the contentView of the TableViewCell and make it fill the space. We also have an initializer that takes in the data and we'll use the same setup method. Now, let's use this. Let's go to EntityRowView+LayoutTest, and let's fill out these methods that are missing implementations. For the reuseIdentifier, we just saw that we can take the EntityRowViewCell.Constant.reuseIdentifier and return that.
Now, when we need to registerClass on the TableView, we're going to use the standard TableView method. Register Class, and from here, we're going to use the EntityRowViewCell.Self to get its type, and ... Let's reformat this a bit. We can select this and hit Control + I to auto-reformat. For the reuseIdentifier, we just defined it above, so we're just going to use that reuseIdentifier.
Next, we have the heightForTableViewCellForCatalog fromData. For this, I'm just to return 100, but you could use automatic table view cell sizing or you could use some sort of height calculation method if you have one. Now, in the TableViewCellforCatalog fromData method, we're going to return a cell, just like we would in the data sources method, cellForItemAtIndexPath. So, as you see, we have a reuseCell here, so first, we're going to check if the reuseCell is nil or not.
If it's not nil, and it's of the type that we need, EntityRowViewCell, we are going to call that setup method on it with the data that is passed in. Then, we'll just return this. Otherwise, it's not the type we want, or it's nil, so we're going to return a new EntityRowViewCell using the initializer with data that we just saw. Now, we've implemented the ViewCatalogProvider protocol. Everything is set up to provide information to show the catalog view.
But now we have to actually display it in the app. So to do that, we're going to need to go to the app delegate and show this view controller. There are plenty of different ways to do this, but this is the easiest way I can show right now. So, in order to do this, we're going to set the window to a UIWindow with its frame being the UIScreen.main.bounds. This is how you used to do it before storyboards. Now we're going to create a rootViewController that's equal to the catalog.
Now you see it's not autocompleting, and that's because we did not import LayoutTestBase here. So let's do that real quick. Now that we have that, we come back here, type CatalogTableViewController, and it autocompletes. Now we want to set the RootViewController's viewProviderClass to EntityRowView.Self, because EntityRowView is the one that is actually implementing the protocol.
Now, we will call the window.rootViewController and set it equal to a UINavigationController and set the rootViewController of that to what we just made rootViewController. This is going to make it so there's a navigation bar up top so that nothing is flowing under the status bar. Now we can call window.makeKeyAndVisible, and return true. We should be all set to go now.
So if we just make sure we're on the UsingTestDataCatalog target, pick a simulator, and hit Command + R to run or hit the Play button. It should work, but it doesn't, because there's one little error here. We just need to implement the required initializer because this is a subclass. Since we have nothing to do here, we'll let the standard fatalError rest there. Now, let's run again. Command + R, and voila.
Now we see every different combination of string and image here, so we can show our designers or figure out if there's something in our code. Huh. As I'm scrolling here, I see that the image on the left is actually disappearing sometimes. It seems like maybe it's compressing all the way down to nothing or disappearing. Maybe similar to the share button, as that was compressing in an earlier section. Let's take a look at this. If we come back to the zip here, EntityRowView.zip, and we take a look at this image, let's assume maybe it's the same as the image over here where we need to change the compression resistance to be higher so that it doesn't compress all the way.
Let's try that. We'll increase by one. And we'll rerun. Command + R. Let's take another look. Ah, much better. Now it's there. So what was happening was the string was longer and it was making this compress down to zero and disappear. So it's very important to get these compression resistance priorities correct. The catalog view is a feature that is still in beta and has not seen much adoption as of this recording.
However, it is quite a useful tool when working with designers or product managers. One way you may want to start working with it is by first creating a view showing it in a catalog to see all the edge cases, and then you can fix any issues before incorporating it into your app. If you have multiple view catalogs to show, you can create a rootTableView with rows corresponding to each different catalog view controller. This way, you can have one catalog view app for all views in your application. You can also create a catalog view with a UICollectionView which is a very similar process.
For more information, look at the LYTViewCatalogProvider.swift header file.
- Installing the library
- Specifying test data
- Reviewing property-based testing
- Using test data and writing the LayoutTest test
- Testing views at different sizes
- Debugging with snapshots
- Dealing with common errors
- Advanced debugging tips
- Exploring catalog view