The colored oval area is where we would like to share as much stuff as possible between platforms. Keep in mind that there are third party libraries that don’t support tvOS or iOS, then, it would be platform target specific.

Hands-on

Before we get our hands on the sample project provided and what each section shares, I’d like to explain very briefly what the ribot iOS & tvOS Apps do. They have the same functionality which is basically gathering a list of ribots from the ribot’s API and displaying their names along with their ribotars. This idea comes from a similar App that we have internally developed at ribot which helps us find out where every ribot is in our new big and shiny studio by using iBeacons. Check our case study!

By the way, if you are still wondering who the ribots are… let me introduce you to them!

The structure of the project is very simple, we are going to be mainly looking at these 3 groups:

Shared group: We will find all the shared classes between iOS target and tvOS target.

tvOS group: All the classes tvOS target specific.

iOS group: All the classes iOS target specific.

Now, let’s have a look at the structure of the Apps and how we can reuse code for each section.

Third Party Managers:

In this case, we are going to be using SharedNetworkManager. At ribot, we are big fans of descriptive names, regardless of length. By reading the name of the file you can almost tell what you are going to find inside it, so, have a guess :-) Yes! SharedNetworkManager is going to be our shared class in charge of the networking, in this case, specifically talking to the ribot API. If you have a look inside it, you will see that we are just making an API call to retrieve the list of ribots by using the library Alamofire (Well known in Objective-C as AFNetworking). This class would be used by both platforms as the functionality would be exactly the same.

Data Manager:

We always tend to use a Data Manager in all our Apps. It is the brain of our Apps and its aim is to reduce the amount of work that Controllers, Models and Managers have to do by providing data that is ready to display, store or work with. However, as I’d like to call it:

“The middle man — sitting between classes, ensuring harmony across the App by handling everyone’s needs.”

Therefore, in this case, the Data Manager is in charge of asking for a list of ribots to the Network Manager, sorting it and passing it back to the Controller which just needs to send it to the view to be displayed as it’s already sorted. This functionality is exactly the same regardless of what platform the App is running on, therefore, it makes sense to share the code.

Model

Since we are making the same request to the API, retrieving the same collection of objects and displaying the same data for the iOS App and the tvOS App, surely the Model would also be the same, right? Well, not necessarily, this is a very easy and specific case. Sometimes this won’t make much sense as Models can get very complex with multiple extensions and supporting different libraries which may not work for both platforms. However, in my opinion, I think there is always space for sharing some base Models between platforms.

So far, we haven’t had the need of splitting any functionality between platforms. Every task we’ve tackled can be applied to both platforms. This will change when we focus on UI.

Controller

In my opinion, this is the exciting part as it truly defines the concept of taking advantage of sharing base classes between platforms.

If we have a look at SharedRibotTeamViewController we will see that we are using some UIKit classes that are supported by both platforms, such as:

UICollectionView

UIActivityIndicatorView

It makes sense to implement the basic logic in this controller. However, be aware of the importance of having a good class structure where each function has clear responsibilities. You may want to subclass the controller for each platform so you are able to customise and make the most of UI platform related components.

iOS: An example of an only iOS UI component is UIRefreshControl or AKA Pull to Refresh which will only be available for iOS. How do we add a pull to refresh which just works for the iOS App? Easy, we just need to create a new class under our iOS target, subclass it of SharedRibotTeamViewController and add it to the controller.

Pull to refresh

tvOS: The same happens for tvOS. We now have the ability to customise the UI and make it look more native.

Have you seen those amazing parallax Apple TV effects when on focus yet? They are fairly easy to turn on, you just need to enable “adjust image when focused” in your image views.

Another common Apple TV collection views pattern is that the footer text won’t be visible until the collection view cell is not on focus. To add this functionality you will need to create a new class under your tvOS target, subclass it of SharedRibotTeamViewController and add the desired functionality.

One of the great improvements of Xcode 7, is that it lets you create your tvOS icon parallax effect within Xcode just by providing front, middle and back layers. Once you’ve added them, Xcode lets you preview them within the xcassets folder.

Xcode Apple TV icon parallax preview

For those who don’t have Xcode and still want to play generating parallax effects, you can download Apple’s Parallax Previewer.

I highly recommend you to try this as it is incredibly fun and easy!

Next steps

It’ll be interesting to see how well this could work for all Apple platforms, watchOS, tvOS, OS X, iOS. However, since the UI is very different we will consider just creating a shared layer of logic between the 4.

Have you tried building something like this yet? I’d love to hear your approach! If you wish to share anything or have any questions, feel free to drop me a tweet!

Also, if you liked this article you might also like what I wrote about Using iBeacons to track our team’s location in the new ribot studio.