iCloud Storage gotcha: Apple inserts a UUID into the filename when storing

My new flash cards app, Fresh Cards, uses iCloud for syncing data between macOS and iOS devices. I’m learning a lot about how to use iCloud Storage, and there are quite a few gotchas and documentation is kind of sparse online, so I figured I’d go through something that I just learned about it here.

Apple recommends using an NSMetadataQuery to keep track of any changes to the iCloud storage folder. Whenever files change in the cloud, any query notification handlers you’ve set up will be called. This gives you an opportunity to go through the list of remote files and see if there’s anything that changed of interest to your app.

The way I handle changes in the cloud is to enumerate the results in the NSMetadataQuery object. I call query.result(at: index) to get each item. Each item is just a NSMetadataItem and you can call value(forAttribute:) on each item to get a whole bunch of info:

  • NSMetadataItemFSNameKey to get the filename
  • NSMetadataItemFSContentChangeDateKey to get the last modified date
  • NSMetadataItemURLKey to get the file URL on disk
  • NSMetadataItemPathKey to get the path to the file on disk (same as file URL but in path form)
  • NSMetadataItemFSSizeKey to get the file size

In my code, one thing I was doing that was bad was using the file URL to determine the filename. This isn’t necessary since NSMetadataItemFSNameKey already gives you the filename. I didn’t realize this at the time.

Anyway, you’d think that the filename in the file URL would be the same as the NSMetadataItemFSNameKey value, but it’s not! Apple actually inserts a UUID into the filename here. I understand why they’d do this. Whenever you upload a file to the iCloud storage, they probably do this to avoid collisions if more than one device is uploading the same file. At some point, they have some conflict resolution and they essentially just “point” to the winner.

For my purposes, I was uploading files that looked like “B565B1E0-B5B8-420D-9792-0CE51911697C.journal”. I had my own scheme where I would use a UUID to make filenames unique as well. But, since Apple was also inserting a UUID into the filename, I started noticing the file paths and file URLs provided by NSMetadataQuery as looking like “B565B1E0-B5B8-420D-9792-0CE51911697C 20CE63AC-AECF-43B9-B5B0-382DD1C8C49B.journal” instead. This threw me off since I thought my app was uploading these errant files. Once I figured out that Apple was doing this, I was able to correct my app behavior to just use the filename from the NSMetadataItemFSNameKey attribute, which is always what you expect it to be (i.e. without the additional UUID inserted).

tl;dr – Apple inserts a UUID into your filenames when storing iCloud Storage, so “foo.txt” becomes “foo 2445A03E-15B0-4DB8-ACC4-62A29B8DE9C5.txt”. Make sure you use NSMetadataItemFSNameKey as the actual filename and not the lastPathComponent of the fileURL or path you get from the metadata item.

Beta testing continues for Fresh Cards!

Work continues on Fresh Cards! Fresh Cards is a new flash card app I’m developing for macOS and iOS.

I’ve been refining the lesson UI, trying to make it easier and easier to use. At the moment, the app has three tabs per deck, one for the next lesson info, one for the list of cards, and one for the stats. After using this app for several weeks now, I’ve realized that I’m always switching between the lesson info and the stats screen. It dawned on me that it makes sense to combine them for a one-stop shop.

Here’s a sneak peek at a design mockup I put together last night in Inkscape:

If you’re in the app to view a lesson, you’ll see it right away. However, if you’ve already done your lesson and just want to see info on your next lesson or other trends, you’ll see them right away too.

Simultaneously (yes, I’m doing all of these tasks at the same time), I’m getting the iPhone version of the app up and running. There’s a lot of shared code, so the majority of this work is building up the UI for iOS. Nearly a year ago I was working on an iPhone flash card app (sort of v1 of this project), and thankfully I’m able to reuse a lot of the UI here to save time.

I need your help to make the best flash card app ever

tl;dr I’ve built a new flash card app for macOS (with iOS coming soon) and need your help to make it the best ever. I will send you a free copy to help beta test it. Just email me at ussherpress at gmail.com.

Just want screenshots? Scroll down here.

[animated GIF removed later]

Okay, some background: I’ve tried existing flash card app options and found them sorely lacking. The big ones I’ve tried are Anki and Tinycards. I’ve also tried some flash card apps by smaller developers and still can’t find anything that I think is good.

Anki
This is the most popular flash card solution out there. The big thing that it’s got going for it is that it’s free. (Well, not so much for mobile.) It uses spaced repetition (awesome) and there are tons of existing decks available for it via ankiweb.

I get that it’s open source, has an open file format, and is extensible, but damn is it hard to use. For non-tech savvy users, what are you to make of this UI? It looks like it’s like something out of Windows XP era.

The lesson UI is also non-intuitive and requires you to make a judgment about how well you were able to recall a card’s contents using a 5-point scale. I understand that this helps make the spaced repetition schedule “more accurate”, but in my opinion, the schedule is just a model of your memory’s “forgetting curve” and if the scheduling is off a few days, I don’t think it matters in the long term.

That said, I think just having a “I remember” or “I’ve forgotten” input is good enough for creating a decent SRS schedule. For most people, a daunting UI is going to put them off studying, so if they give up early, it doesn’t matter how accurate the system is.

In my opinion, Anki is geared more towards users who are happy to install the latest Linux distro, but for the average user, it’s not a great solution.

Tinycards
This is a great online solution. However, Duolingo is shutting it down on September 1, 2020.

What makes Tinycards shine is it’s very easy to use UI and catalog of user-created cards. It’s hard not to like this app because it’s fun and creating new decks and cards is so simple.

The one huge drawback to me is that this is an online service. There is a devoted fanbase, but now that the service is going down, what will you do?

Various app solutions
I won’t name any specific solutions here because I respect that being an independent developer is hard work. I found several macOS and iOS flash card apps and they are functional, but the one thing they always get wrong is the user experience! Folks who create flash card solutions are often very technically savvy and end up creating solutions that work for them, but not the average user.

You can see this by how many settings they’ll throw at you. This is great if you “get” how spaced repetition works and are a power user who doesn’t mind getting your hands dirty, but again, for the average user, something like Tinycards’ UI is “good enough”.

I just tried an iPhone app earlier today that had two screens of settings when creating a new deck. Why throw so many options at the user when they are creating their first deck? Make it possible to customize the deck, but don’t bombard the user with those options upfront.

Fresh Cards
So where does this lead us? Naturally, it leads us to my own home-grown flash card app: Fresh Cards.

I wanted to take the best elements of Tinycards and Anki and create a new app that is easy to use and powerful.

It’s currently in beta testing and if you want to help out, I will gladly send you a free copy of the app to help make it the best solution out there. I need input on what works and what doesn’t work!

If you want to learn more, visit https://www.freshcardsapp.com.

Some things that are very important to me, and that I hope I’ve achieved with Fresh Cards are the following:

The app should be absolutely easy to use. It should take as few clicks as possible to create a new deck, add cards, and do a lesson.

It must employ a spaced repetition algorithm. If the app doesn’t use SRS, what’s the point? Ideally the app should have a plugin system so you can define your own SRS algorithm, but for the initial release, it’ll use SM-2.

It should be possible to export and import decks from other users. The file format should be “hackable”. People should be able to open the file format up and create tools to automate creating decks, if they want.

There should be an abundance of stats. You should be able to see how many cards you’ve learned. It should be possible to see how many cards are due in the week ahead.

The app should not require a subscription service. I do not want to have something that requires you to pay a few dollars a month to use. Yes, I will charge a few dollars for the app, but once you have it, you don’t need to pay to use it.

Reach out to me if you want to beta test. I want this to be the “default” go-to flash card app for the average person. I have a macOS version ready to test and an iOS version coming soon. Contact ussherpress at gmail.com for more info.

Finally, here are some screenshots.

Check out SlouchDB

For my apps Lil Todo, ForeverList/Nested Notes, and Little Phrase Book, I created a simple database system that can be synced easily across multiple devices using a cloud store like Dropbox. Well, I’m happy to announce that I’ve been working on generalizing the database/sync engine for those apps and have opened sourced it.

Check out my new Swift-based SlouchDB. It’s a decentralized, syncable journal-based database meant for single-user, multi-client scenarios like the apps mentioned above. You can use it for Mac and iOS apps! It’s available as a CocoaPod, so you can easily consume it that way as well.

ForeverList update: after a week of work, you can download it!

tl;dr – After a week of hard work, the app is mostly feature-complete and available for download as a preview.

Go download the app here.

This past week I’ve sunk about 13 or so hours into working on ForeverList. I’ve done a lot of work. Here’s the list:

  • added deleting of entries
  • added drag and drop support for images and links
  • added drag and drop for notes (you can reorder them or move to to other notes as sub-notes)
  • added undo/redo support
  • cleaned up the UI overall

The biggest amount of work was the undo/redo support. I basically had to refactor the core model for the app as it couldn’t handle undo/redo in its current state. The new version is much cleaner architecturally. It now uses the diff as its atomic unit of work on the database in memory.

Whenever you modify an entry by deleting it or modifying its contents, the change is encapsulated in a “diff” object. At the same time, a reverse diff object is created to undo the action. The diff is recorded to our database journal. Then, if you wish to undo the action, we do two things: 1. we remove the last diff from the journal and 2. we apply the reverse diff to get the database back into its old state. The removal from the journal is necessary because when we write the journal of diffs to disk, we only want to keep around the actions that weren’t undone.

I did a lot of UI cleanup, but there is more on the way. Here’s what the app looks like now. It’s usable, but has a few rough edges here and there.

I’ve decided to put a preview build of the app online to force me to complete it. 🙂 The preview is fully functional and then file format isn’t going to change, so feel free to start using it regularly. A future update will be posted to the Mac App Store.