Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.

Assignment 4: Documents And MapKit

Due: Apr 26, 2020, 11:59:59 pm, v1

NOTE THAT THIS IS AN EVOLVING DOCUMENT and will surely change to incorporate more information and hints as the two weeks go by. UPDATE FREQUENTLY.

Goals

Learn to use:

  • UIDocument abstractions
  • Document Browser
  • MapKit

You will build a biking or running GPS tracker app that saves and displays tracks through the document browser. See the following for a short demo of a running version of this app:

Tasks

The following is a suggested series of steps for you to take, together with approximate points that each step will be worth. You can ignore all this and just emulate the first video above. Doing that gets you full points. However, the following set of steps is a good approach to building this app methodically.

Step 1: Circles (20 pts)

-Emulate the functionality of the Circles app from 4/7.

In your version:

  • the browser should work,
  • "+" brings up another view controller that allow you to visibly create something (circles are easy), saved back to a file that can
  • later be-reopened

You do NOT have to create the Circles app, but slavishly following what I did in the demo and turning in Circles will get you 20 pts (and count as a Good Faith Attempt).

Step 2: Showing a Map (10 pts)

Go through the videos on 4/8 for Core Location and MapKit. On clicking a "+" button we see the map with the user's current position marked, if in view. A button allows the map to be dismissed. No tracking or line drawing needed, an empty Circles file could be written to the file system.

Step 3: Tracking the Rider (20 pts)

  • Set up location updating to get location updates.
  • Keep the user centered in the middle of the screen in a region with an appropriate zoom level. Do this by choosing the last point given in each location update (there may be many), and creating a MKCoordinateRegion with that point as the center, and a radius of 300 meters.

Step 4: Drawing the Line (20 pts)

  • At each call of your locationManager(manager:, didUpdateLocations:), you will be given an array of one or more CLLocations. Draw a polyline connecting the last previous point to all the points given in this call.
  • Overload mapView(mapView:, rendererFor overlay: ) to give your line appropriate attritutes: red, and lineWidth 3.

Make it work on different-sized phones, w/ orientation changes. Make it look decent. Add a control to toggle between map and satellite views.

Step 5: Saving the File and Viewing Saved Files (20 pts)

Write important information to the file. Define a GPXTrack that contains information about the track, including but not limited to the set of GPS points received from Core Location.

You will need to have routines to serialize to and from JSON, which is cast as a Data, which is then written/read to/from the file.

Step 5: Somethin' Else

(10 pts)

No, I'm not talking about a classic jazz album, I mean that you must pick and implement one of the items from the list below to get the final 10 pts.

Hints

  • My first app used the simple format specified below.
struct GPXPoint: Codable {
    var latitude: Double
    var longitude: Double
    var altitude: Double
    var time: Date
}

struct GPXSegment: Codable {
    var coords : [GPXPoint]
}

struct GPXTrack : Codable {
    var name : String
    var link : String
    var time : String
    var segments : [GPXSegment] = []
    var distance = "-"
    var feetClimbed = "-"
}
  • Your GPXDocument override both contents() and load(), and should probably have a property that holds a reference to the current track.

This is an example GPXTrack using the default JSON serialization to put to a file (use a text editor to look at).

Additional Task, and Extra Credit

Pick one or two of the tasks below for the last 10 points of this project.

Pick up to another three for 10 pts bonus for each you accomplish (up to a max of three), or a donut each, your choice. You'd have to come by to pick up the donut. The points will be appliable on either the assign5 or the final (which will be out of 200 pts):

  • (5 pts) Get your app to read and write files with the .gpx extension. Instead of reading and writing .gpx436, read and write .gpx. Here, I'm just asking you to get the UTI setup correct so that the document and browser will allow you to read and write files with the .gpx extension. Doesn't matter what you write. Note that this is more difficult as the straightforward descriptions on how to do this (google) did not work for me. My version of the app can write to .gpx, but only because I use a very general UTI that allows me to read and write everything. I'd like someone to discover the trick of doing this correctly. Might take you five minutes. Or not.
  • (5 pts) Get your app to read and write real gpx files. Your app should be able to write read and write RideWithGPX files. Don't worry, look at this file and you will see the format is dirt simple (though there may be multiple trksegs).
  • (5 pts) Show a pre-planned route. Show the route (w/ a different color) from another gpx file as you are recording a ride, so that the rider can follow a pre-planned route. Allow the user to choose which other ride to use by adding a button to the screen which showing a pre-recorded ride. Must be able to turn this off as well.
  • (10 pts) Poor man's turn-by-turn navigation - The best way to do turn-by-turn navigation is to know when and where you turn onto a different street. We don't have that information, so you can try to use heuristics, like "turned left or right between 70 and 110 degrees and stayed on the new heading two or three points". Display the navigation in a line overlaying the map at the top of the screen. Navigation cues should be of the form: "Turn right in 50 feet", just showing the next turn. Of course, this only works if you have a pre-planned route as above.
  • (5 pts) Map orientation button - Display a little icon (maybe check out MKCompassButton) that when clicked upon changes the map orientation so that either the current direction of travel is "up", or north is "up".
  • (5 pts) Tracking vs not tracking map By default, our app tracks the rider on the map: keeps him/her centered in the middle of the screen with a set magnification. Cease tracking when you detect that the rider has manipulated the display, either moving, zooming, or rotating. Allow the rider to restart tracking by hitting a button, ideally the above map orientation button.