iOS Test Evaluation

Introduction

  • Creating a simple iOS app that allows users to search for movies and view their details. The app should make use of the Movie Database API to retrieve movie information.

Demo

Requirements

  • The app should have two screens: a search screen and a details screen.
  • The search screen should have a search bar that allows the user to search for movies by title. The search results should be displayed in a table view.
  • The table view should display the movie title, release date, and poster image.
  • The details screen should display additional information about the selected movie, including the movie title, release date, poster image, and overview.
  • The app should cache search results for offline use.
  • The app should handle error cases gracefully and provide feedback to the user when necessary.

Bonus points

  • Implement pagination in the search results table view.
  • Allow users to save movies to a favorites list.
  • Add unit tests and UI tests for your code.
  • Offline mode: the app can persist the data previously fetched and see them when the app is opened in offline mode.

Installation

  1. Install Xcode version 14.0 and later from App Store
  2. Login or Create an Account on TMDB and Get the API Key from TMDB API Settings Page
  3. Download the project from here
  4. Unarchive the Zip and Open Secret.swift file in Movie+ -> App -> Secrets.swift and replace the value of "API_KEY" with API Key from TMDB
  5. Open Movie+.xcodeproj and build the project with Command + B , upon build success run the project with Command + R.

Technologies Used

  • Swift 5
  • UIKit for UI Development (UITableView, UIViewController, UIView, UITabBar)
  • URLSession for fetching data from API (Image & Search Results)
  • Model-View-Presenter(MVP) as UI Architecture Pattern
  • Core Data for Local Cache with Database (Search Results & Bookmarks)
  • XCTest for Unit Test

Reflections

Decisions

  • Utilising MVP

    Allows us to separate the presentation that UI needs to display in the presenter object, and it also allows us to reuse the existing presenter if we want to change UI technologies in the future like SwiftUI, or AppKit. So the UI, only consumes what the presenter assigns to them.

  • Create an Interactor as a mediator for the Presenter to interact with Remote(URL Session) or Local Data(Core Data).

    In interactor also have specific implementation detail of the object we want to get data with i.e. movie, bookmark, recent search.

  • Make use of the protocol in declaring the type and implementation of the Interactor.

    Allows the consumer of the dependency only to know what available methods in the protocol without knowing the implementation detail. Using this method also allow us to loosen the coupling between dependency and make us easier to test specific object in Unit Test through a method like mock without using the real object which is a hard dependency.

  • Navigation

    I'm using UITabBar to allow users to navigate to a different section easily which is usually in bigger applications inside specific tabs containing the sub-functionality of the application.

  • Displaying the Empty State UI.

    Allow giving users a glimpse of information on what action they can do and what is the status of the app-specific functionality i.e bookmarks are empty

Challenges

  • Saving an array of Swift objects into Core Data.

    Since Core Data not supporting custom attribute types, I had 2 options to make to save the search results without creating an entirely new entity, either using Binary Data or Transformable. I'm choosing Binary Data as the primary option because it is easier to convert the Swift object into Binary Data with the help of the JSONEncoder object. In addition, I also don't need to make additional changes to my existing Swift object.

    In comparison, if I'm using transformable type I need to change my Swift object from Struct to Class, then need to conform to NSSecureCoding and assign custom implementation then make a custom Transformer object for Core Data. Since the cache results will be only stored for a certain period of time, we may not need to use this option which also allows us to update existing data easily.