Stopwatch Project

I’m still looking for a new project to work on. Previously, I had mentioned that I built a Podcast Downloader. That project will (still) likely never see the light of day.

I’ve also been working on something else. This is a replica of Apple’s Stopwatch functionality in the Clock app. This project has been open-sourced on my Github account. You can view the project here.

It’s not a complete replica of the stopwatch functionality. I only implemented the digital version and not the analog version. I’m not sure I have the patience to attempt to implement the analog version. I also didn’t implement the iPad or macOS versions of the stopwatch. I only focused on the iPhone version.

Why?

Why did I do this? I did this so I can continue to improve as a software engineer.

I don’t get as much time to write code anymore. At least not as much as I want to. Even at my day job, I spend more time not writing code. I like to believe that projects like this keep me from getting rusty.

As I’ve said, I don’t currently have a personal project to work on. So something like this helps me to continue to learn new technologies and stay current.

Development Process

This project was developed over roughly two weeks. I only worked on it for roughly an hour a night and not every night.

The project has been sitting untouched for a few weeks on my laptop. I wasn’t sure if I was going to post it at all. I finally decided to post it.

The project wasn’t code reviewed or tested too rigorously for issues. It probably isn’t my best work. It also isn’t my worst work. Overall, I’m happy with how it turned out.

Technologies

The project is written in Swift, SwiftUI, and Combine and uses an MVVM-like architecture. I am still learning each of these technologies and approaches.

Swift

I’ve been using Swift since it was announced at WWDC in 2014. I haven’t written much in Objective-C in a few years. Swift is the way to go.

Even though I have been using Swift for years, I still have a lot to learn. I didn’t learn anything new with Swift in this project. Instead, I focused on learning more about the next two technologies.

SwiftUI

I’m still new to SwiftUI. I’ve used it here and there in the past. However, I’ve never built an entire app using SwiftUI. This is a first for me.

This app is simple, but I’ve learned valuable lessons from what I have done.

At work, we’ve been slowly writing new features using SwiftUI. I think the code I wrote here will help at work.

Combine

I’ve been interested in Combine since it was announced. At the time, I had started using Combine for simple things, like dealing with notifications from NotificationCenter.

We use Combine (and RxSwift) heavily at work. It took me a while to start learning the concepts. I still need to occasionally look at guides on Combine. Any extra experience I can get with Combine (and reactive programming) is welcome to me.

I’ve come a long way with my Combine knowledge in the last few years. But I have so much more to learn.

Testing

I have always been an advocate for unit testing. The problem is that unit testing is always the last on my mind when developing. I love the idea of having unit tests, I’m just not very dedicated to writing them.

I’m trying to do a better job of that, including this project. I probably don’t need any unit tests for something like this. The entire project is an experiment. But I need to start somewhere. So, I included unit testing.

I could improve the unit testing in many ways. I could probably use something like ViewInspector to test the SwiftUI views.

I should also provide a deterministic way to test the display strings that are generated by the StopwatchViewModel class while the timer is running. Instead of hard-coding the .main RunLoop in this method:

private func startTimer() {
    timerCancellable = Timer
        .publish(every: 0.01, on: .main, in: .common)
        .autoconnect()
        .sink { [self] newDate in
            let difference = (date ?? .now).distance(to: newDate)
                
            date = newDate
            overallInterval += difference
            currentLapInterval += difference
        }
}
A Swift function that starts a timer

I could start the timer, stop it, and ensure the value is not the default display string value of “00:00.00”, but that’s not a great test. Ideally, I would advance the timer at different intervals and test the results.  

I wonder if Point-Free’s Combine Schedulers Publishers.Timer would work here. This approach would allow using any scheduler (including their TestScheduler) instead of  RunLoop.  This would allow me to advance the schedule as I desired and make the tests more deterministic.

I didn’t use this approach only because I didn’t want to depend on external libraries for this project. It was initially a thought experiment. If I would ever want to make this a full-scale app, I would investigate using Publishers.Timer.

Coverage

Stopwatch App Code Coverage Results - Showing 78.2% Coverage

The coverage on the app is decent. It’s at about 78%. It could be better. I think if I were using a testing framework like ViewInspector, I could test the SwiftUI views and get better coverage.

Summary

I’m happy with how this turned out. I didn’t spend a crazy amount of time on it. I don’t have a lot of time each night to write code. Often, I don’t get any time at night to write code.

This was a fun little experiment.

Podcast Downloader

Since I stopped working on Beer Style Guidelines, I have been looking for something to work on.

I’ve tinkered with a few things here and there. Nothing really stuck until recently. I just finished a small project. I wrote a small app to download podcast episodes.

I have two music (electronic mixes) podcasts that I listen to. I’ve been listening to these podcasts for over 10 years. I decided that I wanted to download all of the podcasts and import them into the Music app.

I initially looked for apps where I could download all available episodes of a podcast and couldn’t find anything I liked. So, I did what most nerds do, I wrote my own.

The podcast downloader that I wrote is written in Swift. It’s a Swift Package that I run via a command-line interface.

I got to play with a few new libraries. I used FeedKit to parse the RSS feed. I used ID3TagEditor to edit ID3 tags on the downloaded MP3 files.  Finally, I used ConsoleKit to log messages and loading progress to the terminal. It was fun to play with some different libraries in different domain spaces.

For a minute, I thought about open-sourcing the project. But I think it could be used indiscriminately. I wouldn’t want anyone wasting bandwidth downloading all podcasts. I was a bit nervous about doing this myself. I decided to send recurring donations to the podcast authors. Prior to performing a full download, I had done a lot of one-episode testing. I also ensured that if the process failed somewhere, episodes wouldn’t be downloaded again.

The entire project took me about two weeks of tinkering. It’s probably not the best-written code I’ve produced, but I’m happy with the outcome.

I now have all of these music podcast episodes that I’ve enjoyed over the years in Apple Music. I can listen to them again whenever I want.

I’m happy that I was able to work on a new project. I even finished it. Even though this project will likely never be released anywhere.

I’m not sure what I’ll work on next, but I am really happy with how this one turned out.

Hiking

I love hiking. I don’t get to go as much as I would like. But I try to hike whenever possible.

Sometimes I’ll even get my family to come with me. But I’m usually alone when I go. I do like it when they tag along. But I understand it’s not their favorite activity.

When I go, I like to take a lot of photos. I don’t know if any of them are good, but I enjoy looking at them later. The photo above is not mine, but Dale Nibbe’s.

Most of my hiking has been in Pennsylvania. I’ve also gone on a few hikes in California. In the last year, I’ve tried to go for hikes wherever we happen to be on vacation. It’s a great way to check out an area.

This year, I finally bought hiking boots. Previously, I’ve always used an old pair of sneakers. But I wanted something that was waterproof. Some of my hikes have been in muddy and wet areas. Wet socks are never fun.

I went for a hike today. It wasn’t a long hike. I was out there for about an hour. I went on a trail that I’ve been on numerous times. So I know exactly where it goes and what I’ll see. It was very cold out today, so the trail was empty.

I haven’t gone for any overnight hikes. As much as I enjoy hiking, I hate camping in tents. Sleeping (or trying to) on the ground is the worst. I’ve had some bad experiences camping and would rather not do it again.

For now, I’m sticking to short(ish) hikes all shorter than a few hours.

Book Renewal

Earlier this month, I mentioned that I had borrowed a book from the library. I was a little nervous about being able to finish the book within the two weeks I had.

I didn’t finish Billy Summers. I made it about 35% through. Yesterday, I renewed the book for another two weeks. I hope to finish the book this time.

If I only made it through 35%, how am I going to finish the other 65% in two weeks? During the first two weeks, we had a lot going on. The Phillies were in the World Series, the Union was in the MLS cup playoffs. Those are over now. I should have some extra time to read, at least until the World Cup starts this coming weekend.

So far the book is pretty good. I really hope that I can finish within the next two weeks. Wish me luck!

Fletch Book Series

I listen to the MacBreak Weekly podcast. About a month ago, Andy Ihnatko’s pick of the week was the “Fletch” book series.

The series is currently free. I believe it’s free for any Audible Plus members (like me). At least I would assume you would need to be a member to listen to the series for free.

There are 11 books in total. The first one was published in 1974 and the final one was published in 1994.  

I’ve been listening to the novels. They are pretty good. They are also short books and you can get through them pretty quickly. I just finished book 3 (Fletch’s Fortune). I really liked the first book. The second two books have fallen off a bit for me.  

In my mind, I picture Chevy Chase as Fletch, just like the Fletch movie. There’s a new movie out with Jon Hamm as Fletch. I haven’t seen that one yet.

If you’re an Audible Plus subscriber and looking for some good books, check these out.

OlderNewer