2021-01-15

iOS App: Hang out Planner

SwiftREST APIDispatchGroupdiffable data sourcesMapKitCoreLocation

Summary

We created a native iOS application with Swift. This app suggests optimized root which includes locations that the user prefers. This app uses modern collection views with diffable data source, async API-fetch with dispatch group.

Motivation

Problem

These days, there are a lot of locations and places where we want to visit. However, it is very difficult to find out which to visit, and next to visit.

This is because,

  1. There are too many places so that it is troublesome to find out decent ones.
  2. Even if you find out them, it is also painstaking to think about the best route. For example, which places to visit first and next so that we can go multiple places efficiently.

Solution

To solve these problems, we created is a great application, which instantly and automatically generates a plan which is a collection of navigation routes based on famous locations surrounded by your current location.

select categories

My contribution

Team manager

As a team manager, I manage the whole schedule and design architecture.

I used notion for scheduling and used the agile style. This makes this project complete in just two weeks!

Schedules Docs Tasks

UI Designer

As a UI Designer, I created a whole UI mock using Figma. In addition to creating a style guide, I create design components that are well suitable for implementing swift codes.

UI mock 1 UI mock 2

Back-end developer

As a back-end developer, I design architecture and algorithms for fetching and suggesting items. I also creating tracking of user location by using core location. I will explain the details later.

Repository

The latest version of this project is as follows.

Hang-Out-Planner

Spec

  • Swift: version 5.4
  • MapKit: To display route and user location
  • Core Location: To get the user current location
  • REST-API: Get external location data from yelp.
  • Collection View: With diffable data source.

Usage

Flow

The user first selects some categories of locations with the order. Then the app will fetch locations surrounded by a user and calculates auto-suggests the best (most famous and closest) route includes locations that belong to the category user has chosen.

For example, if a user chooses 'Restaurant' ➔ 'Nature, Park' ➔ 'Art' in New York, the app will suggest the route 'SHAKE SHACK' ➔ 'Central Park' ➔ 'Carnegie Hall'.

How to use

  1. A user selects some categories with their preferred order.
  2. After deciding categories, a list of plans is displayed to a user.
  3. After selecting a plan, a user can look at its details with routes on the map, distance, cost, and so on.
  4. Of course, users can see each location's data.
todo planner location-manager

Back end contribution

Here are the details of the contribution that I did as a back-end developer.

Fetching user location

The app fetches the user's location in two ways, locationManager and IP address. When you visit the target screen, we set the location manager to start fetching his/her location. Even a user denies it, we can assume approximate location by using an IP address from API.

Fetching location

This function will be executed at sceneWillEnterForeground and viewWillAppear

extension LocationController {
  /// Start updating(tacking) user location
  /// - Parameter completion: an action you want to do when the user location is updated.
  func start(completion : @escaping(()->Void)) {
    locationManager.requestAlwaysAuthorization()
    locationManager.startUpdatingLocation()
    isUpdatingLocation = true
    self.completionDidLocationUpdated = completion
  }

How to suggest the routes

DispatchGroup

After a user decides their categories, this app asks API (yelp) to fetch related locations. It will ask serval times to get different times. These fetching are executed as async and concurrently. Once all fetching has complete, we proceed to the next step. These processes were implemented by using DispatchGroup.

group.enter()
    NetworkController.shared.fetchLocations(
      group : group,
      category:CategoriesForAPI.amusement,
      completion: NetworkController.shared.convertAndStoreLocation
    )
// This is executed after "all fetch are done"
    group.notify(queue: .main) {
      
      // Creating final locations with adding user location and assigning id.
      User.allLocations.removeAll()
      User.allLocations = [User.userLocation] + NetworkController.shared.tempAllLocations
      (0..<User.allLocations.count).forEach{User.allLocations[$0].id = $0}
      // Remove temp data for memory saving.
      NetworkController.shared.tempAllLocations.removeAll()
      
      completion()
      
    }

Async Fetching

Fetching images is expensive. Sometimes, if the internet connection is weak it costs a lot of time to get images. In this kind of situation, we didn't want the screen to stop until it fetched and displayed images. So we firstly display place holder and try fetching images asynchronously. As soon as it finished fetching, we replace images so that the user can feel no stress!

look the plan detail

Future work

What we're planning to do next is as follows.

  • Store plans as permanent data using core data or realm
  • Publish in the app store
  • Implement user account by using firebase

Team member

Tak (me :cookie777)

  • Team manager
  • UI Designer
  • Back end developer

Yumi (YumiMachin)

  • Front end
  • Back end (implement image API fetching)

Kengo (kengo-taka)

  • Front end
  • Created ReadMe, Docs.

Works