In the fall of 2017 my friend Julie Bruno approached me with an idea for an iOS coat check app. I recognized the idea had a lot of potential, and I thought it would be a great opportunity to challenge myself and stretch outside of my current knowledge of Swift and iOS at the time. We worked for several months, iterating on her ideas and designs with input from me on what options we had as we designed and implemented the back-end of the app. The main challenge was how to make the app work both online and offline, which proved to hold a lot of hidden complexity that we didn't initially see. We built a working prototype that was fully functional, but we didn't end up launching the product. I realized at a certain point that the project had grown in scope to such a degree that it was more than a single developer could handle on a part-time basis (since I was also working on other projects at the time).
Part of the value for the customer that Julie envisioned was being able to monitor what was happening on the floor in the venue where the app was deployed, offer statistics on how often people were visiting a venue, and also to offer marketing opportunities that people checking in their coats could opt into. With that in mind, it made sense to hold the state of the coat check data on the server and have the app pull that data rather than store it on the device. Complexity creeped in when we tried to figure out what should happen if the device was offline and not connected. I switched the dynamic so that state was held in local storage on the device and synced with the server whenever the device was online. This introduced edge cases, such as what happens if a device is offline for weeks at a time and tries to sync thousands of tags? I did develop a system that worked well during testing when it was one device connected to the server, but ultimately I felt like it was an engineering problem that was more than I could handle as the single developer on the project.
I used a lot of different frameworks for this project: Queuer to handle asynchronous tasks related to saving data from the app to the server where it would be displayed on the website for clients; PhoneNumberKit to handle parsing, formatting, and validating phone numbers (which were associated with the coat check tags to identify who they belonged to); Alamofire to handle the HTTP networking we used to send and receive data from the server; SwiftyUserDefaults which is a much more friendly alternative to NSUserDefaults to store default configuration variables related to the app; OHHTTPStubs to simulate network responses during automated testing; PMAlertController provided customizable alert that improved on UIAlertController; CryptoSwift which was used to hash a security token which was sent to the server to ensure that only valid API calls were processed; CodableAlamofire, an extension for Alamofire that converted JSON data received from the server into a Decodable object in the app; Atributika which allowed us to style NSAttributedString objects using HTML markup; Quick which is a much more elegant way to write automated tests and Nimble which is a matcher framework used to match expected and actual actions in the app during automated testing that pairs up with Quick.