Skip to content

Latest commit

 

History

History
149 lines (119 loc) · 9.55 KB

README.md

File metadata and controls

149 lines (119 loc) · 9.55 KB

Index

iOS Coding Challenge Using SwiftUI

This is a coding challenge for prospective mobile developer applicants applying through http://work.traderev.com/

Goal

Build simple app that allows viewing and interacting with a grid of curated photos from Unsplash: Completed all above criteria.

  • Stack: Swift 5.8, SwiftUI, MVVM
  • Unsplash API docs are here: https://unsplash.com/documentation.
  • Grid of photos should preserve the aspect ratio of the photos it's displaying, meaning you shouldn't crop the image in any way.
  • App should work in both portrait and landscape orientations of the device.
  • Grid should support pagination, i.e. you can scroll on grid of photos infinitely.
  • When user taps on a photo on the grid it should show only the tapped photo in full screen with more information about the photo.
  • When user swipes on a photo in full screen, it should show the the next photo.
  • Preserve current photo's location on the grid, so when she dismisses the full screen, grid of photos should contain the last photo she saw in photo details.

Evaluation:

  • Solution compiles. If there are necessary steps required to get it to compile, those should be covered in README.md.
  • No crashes, bugs, compiler warnings
  • App operates as intended
  • Conforms to SOLID principles
  • Code is easily understood and communicative
  • Commit history is consistent, easy to follow and understand

Installation

  • Remember to use your own API key in the Config.xcconfig file like UNSPLASH_API_CLIENT_ID=12345655 before running.
  • Min iOS version supported is iOS 15, after the disscussion in the last round. Used XCode 14.3.1 for building.

Demo

Demo Photostic iOS Unsplash App

Process Followed

  1. Planning - Divide and Conquer: Created a list of tasks and prioritized it. Check Photostic Project
Screenshot 2024-02-09 at 10 05 24 AM
  1. Unsplash API Spike: Tooks a deep dive at the Unsplash API, seeing what all optimizations it can offer, and came to following conclusions:

    • webP/ AVIF support: These are much better than jpeg or others and best balacing compression / quality. Not supported for free version though.
    • Blur Hash: They provide Blur Hash string that would make a great placeholder. However this was 4x slower than Android, and was making less performance, so I implemented my own version of placeholder using the color they send with each image and a loader. Spend a lot of time trying to make the has work with ThumbHash, which is much better than Blur Hash in terms of performance, but since they use base83 hashing, which is different than what Unsplash provides (base64), it wasn't worth the effort, givent eh time constraints.
    • page size / per page limits / free tier limits: It turns out that for free version many of above is not there like only 10 per page, max 50 request / hour, no custom format etc.
    • Multiple size of Images pre-available for thumb, full etc.
  2. Mocking the API:

    • Simulated a real world enviornment where many time devs don't have API available, so working off Mocks make it faster.
    • Limitation of free tire were 50 requests / hour, didn't want to cross that.
    • Would be useful for testing anyways.
  3. Implemented screens and flow using the mocks.

  4. Added following

    • Network logic using async await,
    • Caching (in-memory),
    • MVVM pattern,
    • Pagination,
    • Splash Screen,
    • App Icon,
    • Tests etc after that.
  5. Note: As a best practise, following PR process. It also showed I like to be detailed and explicits with PRs for easier review process. Sample Pull Request can be found here: PR:# GridView and DetailsView Screens with Mocked Data

Optimizations and Best Practises Incorporated

  1. CLIENT_ID / API_KEY not included in the project, and in separate config file, which is added to gitignore. Add your key to Config.xcconfig before trying to run project.
  2. Offline friendly app, with in-memory cahing of images as well as API responses. Faster load times for images, and prevents unnecessary calls.
  3. Error Handling done to show user alerts.
  4. Constants at the top of file (could have been in a global file as well)
  5. Customized Placeholder almost similar to blue effect, of exact the size of image, while maintaining the aspect ratio.
  6. thumbnail size for grid view, and regular for the details.
  7. NetworkManager's implementation is mockable.
  8. Added a few Unit / UI tests to show possibilities.
  9. Rigorous manual testing with network simulator, multiple device sizes and modes etc.
  10. No 3rd party libraries.

Optimizations Considered and Tried

  1. AsyncImage: Implemented it initially but doesn't supports caching, so removed.
  2. Memory mangagement: Considered implementing custom LazyTabView for image gallery. The TabView is not lazy loading in details view. There is no lazy version of that available unlike, LazyVGrid. An implementation I had was buggy, where I was considering only having 3 tabs, and just replacing images in it.
  3. Network Monitor to monitor when data goes away but wasn't worth this time, after dwendling into it for a while with simulators.
  4. Tried snapshot testing, but due to shortage of time, couldn't set it up.

Future Optimizations Possibilities

Image Optimization

  • Incorporate webP / AVIF format if/when I was on the paid API plan.
  • Deciding Image quality to load based on network quality (releavnt with remote dealerships) - multiple libraries do that.
  • Depending on need, try disk based caching instead of in-memory for longer lasting cache.
  • For the cache size, look into optimizing the max allowed size.

Network / API calls Optimizations

  • Cancel the tasks to download image if user already scrolled fast past them or look into reprioritizing.
  • Retry API calls with exponential backoff after network failure.
  • Consider decouping Network layer more maybe using a Factory pattern, such that if we use multiple Image APIs in future, the interface and logic of rest of the code remain same. We only need to make
  • Consider implementing Repository pattern around APIs to read from local data if data not returned from remote.

Features / UI

  • Pinch to Zoom on details page
  • When user swipes on details and reaches last image, make an API call to fetch next page from details view.
  • Make the views more accessible, eg: Apple Accessibility guidelines talk about having buttons irrespective of gestures on the views.
  • Animations
  • Dark Mode support
  • Add brand colors

Coding Standars / Readability / Quality

  • Implement Logging (remote) using Singleton pattern for better debugging.
  • Localization Support rather than harcoding strings
  • Separate constants in the codebase for better readability.
  • Better testing coverage.
  • Including performance benchmarks, performance tests, snapshot tests, accessibility testing (and following best practises).
  • Feature flags (maybe not needed for simple ones)
  • Look into the need of Details view needing it's own ViewModel? Maybe when we have a fetch call to next page from within the Details View?

Screenshots

iPhones

1 2
3 4
5 6
7 8
9 10

iPad

1 2