Saving Data in iOS

May 31 2022 · Swift 5.5, iOS 15, Xcode 13

Part 2: JSON

13. Saving On Device

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 12. Challenge: Decoding JSON Arrays Next episode: 14. JSON Encoding

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Notes: 13. Saving On Device

Apple’s Bundle documentation

This course was originally recorded in April 2020. It has been reviewed and all content and materials updated as of November 2021.

Transcript: 13. Saving On Device

In this video, you’ll begin working with files in the user’s app Sandbox. Up until now you were decoding the JSON data from files in your app Bundle, that is, in files that were already added to your application prior to building your application binary.

Now, you will start saving and manipulating files to the Sandbox, where a few folders are available to you.

You’ll continue to work in the loadJSONPrioritizedTasks method and start by adding print statements to visualize the path of your app Sandbox versus your app Bundle. Add a print statement at the top of the loadJSONPrioritizedTasks method.

print(Bundle.main.bundleURL)

Then, run the app in the iOS simulator and look at the console.

You can copy that URL’s path, click on your Desktop or the Finder icon, and then hit Command + Shift + G.

Paste the path in there and hit Return.

Note that even though your path may have included the /TaskList.app/ in the path, Finder takes you one folder up. What you can do to truly go into the app bundle is right-cilck the TaskList app, and select “Show Package Contents”.

This is your app bundle, and as you can see, it contains your resources including the JSON files being loaded. The bundle, in this case, corresponds to your iOS app and all the contents that get added when creating it via Xcode.

Next up add a print statement to show your user’s Document directory URL. This will be the app-specific Document directory.

print(FileManager.documentsDirectoryURL)

Run your app, in the simulator still, and follow the same process of, via the Finder, hitting Command + Shift + G to be able to enter the folder to go to. This time paste the path to the Document directory.

This corresponds to your app sandbox’s Document directory. Right now it’s empty because you’re not storing anything there to be read back. The Document directory is outside of the app Bundle, in a separate location within iOS that keeps your user data, on a per-app level, compartmentalized.

There is one more directory that I want to show you. So add the following code right after your last print statement.

let temporaryDirectoryURL = FileManager.default.temporaryDirectory
print(temporaryDirectoryURL)

Run the app in the simulator one more time and check out the path in the console. You don’t need to open this folder if you don’t want to, but notice how the majority of the path is identical except for the last directory within the sandbox. It’s a folder called tmp as opposed to Documents, which is the one you’ll rgularly work with.

tmp is a unique folder for when you want to store temporary data, cache any files, images, etc., that you don’t need to ensure they permanently persist.

If you were to encode and save your tasks into the tmp folder, iOS can purge its contents at any time, causing you to lose that data. This is why, for storing the very important set of tasks, their priorities, and completed status, you will use the more permamenent solution in the Document directory.

Until you save your tasks to the Document directory, go ahead and copy the PrioritizedTasks.json file from your project folder into the Document directory printed out in the console.

Note that, for this, you will need to use the iOS simulator so you can easily copy and paste files into these folders, something not so easy or straightforward if done in the simulator.

You are going to get rid of the guard statement in loadJSONPrioritizedTasks and instead load the URL in a way you are already familiar with.

let tasksJSONURL = URL(fileURLWithPath: "PrioritizedTasks",
                       relativeTo: FileManager.documentsDirectoryURL).appendingPathExtension("json")

That should be similar to how you constructed URLs in playgrounds when experimenting with the FileManager, URLs, and paths.

FileManager also provides you with a handy method contentsOfDirectory(atPath:) to acquire a String array of the contents of a particular directory, which will be perfect for knowing what files are available in your different sandbox directories.

print((try? FileManager.default.contentsOfDirectory(atPath: FileManager.documentsDirectoryURL.path)) ?? [])

The call can throw, so you mark it as try, and since it can return an optional you simply nil coalesce it to an empty array. The only parameter this method takes is a String with the path to the directory you want to get the contents for, and you print out the results so the array of files can be seen in the console.

Build and run your app in the iOS simulator, and, if the JSON file was copied to the right location, it should be printed out in the console when you run.

And there it is! You are now loading your tasks from the file in the Document directory and not from the app bundle. This will get you halfway there when it comes to loading and decoding your serialized prioritized task data.

The other half is saving the data to the file, and persisting that data when you make edits and across app launches.