Accessing an SMB share in iOS using Swift

As you might guess from my Books page, I read/listen to a lot of books. It became apparent that I needed a way to track all of these books, basically just for my own sanity. I’m not sure if you are like me but when you read this many books, I really don’t remember all of them (most of them?). There are a lot of series in there that span years, so I often forget which ones I’ve read.

To alleviate this problem, I wrote a book database app for iOS/iPhone, using Swift and SwiftUI. It’s super simple, only has a couple of screens but as important as tracking my books, it allows me to search them. This is invaluable. Here are a couple of screenshots:

Books by year tab

Search tab

Since friends and family will ask what I’m reading, I decided to add the ability to post my list of books read to this website. It’s just a json file that lives on my server and is read by a script. The catch was when I first wrote the app, my website was hosted and the only way to push files to the server was via FTP. iOS supported FTP upload a long time ago and while depreciated, it still worked. And once you have something working, you tend to forget about it. When I moved to self hosting my website, FTP was quick and dirty to get going and I only had to change the login data inside the app.

But all the depreciated warnings bugged me, so I set out to move to SMB, as my server has a bunch of shares on it for various other things. iOS added native support for SMB way back in iOS 13 but it was pretty low level and I could never find any good example code on the web to work from. Fast forward to this week and I finally have tackled the problem thanks to a super easy SMB client library I found on GitHub.

The readme has very clear instructions, although I think he changed the fileName property to name in all instances and just forgot to update it. It really was as simple as adding the library via the Swift Package Manager (SPM), importing the library into my helper swift file that deals with saving the data, and then following the code examples under “Usage”. The author doesn’t use any do {...} catch {...} blocks to deal with errors in the example code but they are easy enough to implement. If you incorporate this functionality using a function, you’ll need to mark it as asynchronous and use a Task to call it, again pretty straight-forward. I commented out the old FTP code, tested, and everything worked. Sweet!

I’m not sure it’s worth providing more code here, given the extent of code in the readme on the GitHub page but if you have any questions, feel free to contact me or leave a comment.

Updated:
Uploading a file using this client will not overwrite an existing file but will cause a name collision error. You can however, delete the file prior to uploading, which worked find.