There is more common ground than you might think – re-use, reproduce, recycle for faster, cost-savvy development
Nowadays it’s really hard to imagine our lives without all of our communications devices. Every day we watch TV, talk, text and email on our phones, and/or play the latest video on computers and games consoles. TV platform operators today recognise that their subscribers increasingly demand that their favourite online and mobile features – all those ‘go-to’ apps, tools and entertainment channels so familiar on ‘non-TV’ devices – must be easily accessible via TV and set-top box (STB). So they are investing millions of dollars and euros as they strive to meet consumer demand, and deliver these services to viewers as part of a unique and appealing product offering. Faced with ever-intensifying competition, TV service providers are going all-out to accelerate product rollouts wherever they can to try to retain, and moreover, grow, their share of the market, and beat the competition. One tactic to economise on time and investment is to try, if possible, to replicate and re-use already established developments. Development teams everywhere are doing all they can to avoid reinventing the wheel.
Development activities which can be applied to multiple device platforms, rather than being compatible with only one, are becoming prevalent.
The possibilities to re-use, replicate, and migrate innovations from the pure mobile world to benefit the TV app development environment are greater than they may at first appear.
For example, the fourth generation of Apple TV was released in October 2015, and this became a very significant date for companies in the business of providing video, audio and other content to consumers. You may ask: why is this iteration so significant, after all Apple TV has been on the market since way back in January 2007? The answer is because only 4th-Gen Apple TV came with a new operating system, tvOS, with an associated app store allowing users to install third-party applications on it. The new possibility of creating their own brand-specific apps for new platforms prompted companies to start thinking about strategies for quick migration of existing solutions using iOS and macOS to tvOS. They key question was: is it possible to share codebase between iOS and tvOS?
The answer to this question is revealed in their differences. The biggest distinction between iOS and tvOS is the handling of user interaction; an iOS service is operated by multitouch technology, whereas in the case of tvOS it’s remote control.
Apple has a specific system within UIKit called focus engine to make navigation between content items on the screen possible. As Apple’s product documentation explains, most iOS frameworks can also be presented in tvOS, but for some of them, the API is somewhat limited. Those limitations in general relate to the UIKit framework. For example, some classes are absent (namely, UIStatusBar, UIInterfaceOrientation, UIWebView, UISwitch etc). Also, UISearchBar has no public initializer and can be created only by using UISearchController. Furthermore, some properties of classes are also not included (such as UIScrollView – scrollToTop, UITableView – separatorStyle, UIViewController – preferredStatusBarStyle etc.).
However, despite the restrictions of these frameworks, they are still presented in tvOS, and we can use the same classes in the model of application, plus we can also easily share codes of views and view controllers.
There are several primary ways to organize development for iOS and tvOS targets:
- Separate projects with linked library of shared code;
- Workspace, containing a project for shared code, as well as projects for iOS and tvOS targets, and linking setup;
- Single projects with multiple targets and conditional compilation.
Let’s analyze each of them.
|1. Separate projects with linked library||• Clean code
• Less build time (framework is already compiled)
|• Even small changes in shared code will require a lot of time
|2. Workspace, containing a project
for shared code
|• Easy to make changes in shared code||
• Increased build time
• Increased time to solve conflicts in project with shared code
|3. Single projects with multiple targets and conditional compilation||• Easy to maintain||
• Not as clean as first and second approaches as shared classes are placed at same location with platform specific implementations
All of these approaches are valid, but for projects requiring active growth of new features and tight time constraints it’s very important to minimize operational losses. In this situation, conducting single projects which fulfil multiple targets and objectives with conditional compilation is by far the best method.
To ensure the project is well-structured, and to avoid what could become indecipherable chaos, you need to define a list of code separating rules:
- Interface builder files have multiple versions, i.e. EPG~mobile.storyboard and EPG~tv.storyboard, since they are incompatible with each other.
- Code which can compile and works identically on both platforms is included into both Mobile and TV targets.
- If code doesn’t compile for both targets or needs to work differently, depending on the target, the following ways to resolve this can be used:
- Conditional compilation directives (#if tvOS()) – are discouraged, but can be used for short pieces of code, which only compile for one target and are difficult to extract otherwise. The consideration here is that with the conditional compilation it’s harder to notice which code belongs to which target.
- Interface idiom check – using runtime check to determine device type. Only relevant for cases where code compiles for both targets, but there are slight differences in behavior. As with the previous way (a), this also should only be used for small pieces of code. If a particular source file has a lot of interface idiom checks, consider using extensions or subclassing to separate shared code from device-specific code.
- Device-specific extensions – code relevant for a target is extracted into a separate extension of an otherwise shared type, which is then included only to the relevant target (i.e. RootViewController+Mobile). This method is recommended for types which don’t have semantic difference for different targets.
- Device-specific subclasses – for every target a separate subclass is created, which contains code differences, while shared code is saved in a superclass. Should be used for types which do have semantic difference for different targets (for instance, if list has a two-dimensional layout on TV, but is only vertical on mobile).
These rules are not a magic key which resolves all possible issues, but, my fellow developers, they sure will make your life easier!
There is in fact much commonality between iOS and tvOS, and you can re-use the majority of code platforms. With the help of rigorous techniques, smart coding rules, thoughtful UI/UX design, and Apple tools, it is possible to achieve great cost/time/effort efficiency while effectively building multiple applications.
Author: Alexey Sergienko (iOS Technical Lead at 3SS), www.3ss.tv