Weekly Project Update 4
No preamble today. Let’s get straight to the update.
Day One Sync
The core of the app is coming along. Feeds are being polled and new items are being added to Day One using the command line tool. I’m in the process of testing this on my own blog posts. I’ve disabled the IFTTT RSS-to-Day One integration and I’m now relying on this to harvest these posts and add them to Day One. It’s already a massive improvement over the old system. For one thing, the formatting of blog posts is preserved, meaning I no longer need to fix this myself. The tool is also uploading any images included in the blog post to Day One: no more weird links to IFTTT in place of images. The core is by no means complete, and it’s also an ugly mess that needs a fair bit of rework, but it’s probably something that could be set aside for a little while.
Now comes the hard part: making the UI. I say “making the UI” because what is in place at the moment is only barely functional. It’s just enough to get the feed polling stuff working, but it’s not in a state that I’d like to share with others, or even use myself. However, I’ve made the first steps towards that, with replacing the main view controller with a SplitViewController. It was less difficult than I expected, and it’s nice separating concerns across multiple classes. It does make communication across the view controllers a little more difficult. I’d rather not have view controllers know about each other, as that just increases the coupling between them, making the code difficult to work with down the line. Instead, I’m opting for an event-based approach to do this, and I’ve found a relatively simple library, called SwiftEventBus, to do this.
I’m hoping for a UI that looks at home on Big Sur, complete with the split toolbar seen on apps like Mail and XCode. Thanks to this WWDC video and this blog post, I managed to achieve this yesterday. I must say that it provides a nice way to separate the toolbar items based on what they operate on: the buttons on the left operating on the list of feeds, and the buttons on the right operating on the feed itself. I had a bit of trouble getting the
NSTrackingSeparatorToolbarItem aligned with the segmented control though. Many of the examples set the
1, which I guess works on a three-column window. This app only has two columns though, and it was only when I set
0 did the divider nicely align with the split view. Also, given that this class is not available in the storyboard palette, I had to change the toolbar so that the items are now being created in code. This may end up being an advantage though, as I’d like the items on the right to change based on the controller being shown in the details view.
One last thing that took me a while to figure out is how to send events to the first responder from code. Since the toolbar items are being created in code, I couldn’t rely on the connections defined in the storyboard. I’d also didn’t want to add the
IBAction to the window controller as I could imagine that being unwieldy as more actions are added over time. So I’m using the pattern described in this Stack Overflow answer, which involves using a selector for a function definition on a protocol. My first attempt at this was producing the error
unrecognized selector sent to instance. It was only after reading this blog post that I realised I was setting the target incorrectly. It was being set to the window controller, which did not implement the protocol. Setting the target to
nil resolved the issue, and I was able to send events that were being picked up by view controller in the responder chain that implemented this protocol.
This is now working for adding new feeds. I now need to make it work for removing feeds, which I’d like to be handled by the view controller representing the feed. This view controller is instantiated in code when the selected feed in the outliner is changed, but it does not seem to be included in the responder chain, and the events to delete the feed are being lost. That will be the next thing I tackle.
That’s all for this week. Until next week.