# 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](https://sedna.cs.umd.edu/436clips/circles.mp4) 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](https://sedna.cs.umd.edu/436clips/OUT12coreLocation.mp4) and [MapKit](https://sedna.cs.umd.edu/436clips/OUT12mapkit.mp4). 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 `CLLocation`s. 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](assign4Example.gpx436) 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](https://gitlab.cs.umd.edu/keleher/iosstudents/-/blob/master/assign4bmwRS1200GS.gpx) and you will see the format is dirt simple (though there may be multiple `trkseg`s). - (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.