Building a MacOS Menu Bar Application
For a first foray into MacOS development, we built a menu bar application. The Hijri Menu Bar allows the user to view the current Hijri date. It is convenient, minimal and easy to use.
Below, we’ll highlight the development process, looking at the code, build process and challenges faced.
Development
The development process began with setting up the project in Xcode. We used Swift and SwiftUI as the foundations for the app. We incorporated essential components such as the AppDelegate, which manages the apps startup and background tasks. We then created a custom StatusItemView
to handle the UI and what the user would see.
App Delegate
The AppDelegate
class is responsible for setting up the status bar item, managing the popover and handling user interactions. It initialises a clickable item in the menu bar with a calendar icon.
We then create an NSPopover
to display a SwiftUI view. This popover is essentially a holder to display the contentView
. Here, we’ll use a StatusItemView
(discussed later) to display the actual Hijri date information within this popover.
The button.action
and button.target
lines establish the target-action pattern. Clicking the button triggers the togglePopover(_:)
function (defined below). This function essentially decides whether to show or hide the popover based on its current state.
The togglePopover(_:)
function checks for the validity of both the button and popover.
If the popover is already shown, it will close it. If the popover is hidden, it first fires a notification .fetchHijriDates
. This will be received later in our StatusItemView
. Finally, it displays the popover relative to the menu bar icon’s bottom edge.
Applications in MacOS can have different activation policies that determine how they behave in the user interface. Setting the activation policy to accessory mode means that the application will remain active in the background, even if the user closes its window or quits the application. This is useful for menu bar applications that need to remain running without requiring constant user interaction.
User Interface
After configuring the AppDelegate, the focus shifted to building the user interface. This lies in the StatusItemView
, which will be responsible for displaying the current Hijri date in the popover we created above.
This view manages the date fetching and presentation. The app starts with state variables which will store the current Hijri dates in Arabic and English.
Next, we useText
views to display the current Hijri date in Arabic and English with appropriate formatting.
We utilise a horizontal stack HStack
to display a copyright message and an information icon. Tapping this icon toggles the visibility of the instructions menu (which we coded in a separate InstructionsView
).
The app fetches the latest Hijri dates in two ways: When the view first appears on the screen, it grabs the latest date for an accurate display.
But we noticed this did not seem to refresh the dates, say after midnight. Therefore, the notification fetchHijriDates
is triggered from the AppDelegate
every time the popup is shown. Here, the StatusItemView
listens for this notification. When it is received the function it fires the fetchHijriDates
function (explained next) which handles fetching the current date.
Behind the scenes, thefetchHijriDates
function fetches the current Hijri dates. It formats them according to Arabic and English locales and updates the state variables with the formatted dates. It is called both when the view appears and in response to the fetchHijriDates
notification, discussed earlier.
Here we were able to leverage Apple’s built-in Date and Calendar functionality, using Calendar(identifier: .islamicUmmAlQura)
. This (satisfying) pre-built functionality saves us time and ensures accuracy in our date handling.
Full code can be found at: https://github.com/Enamulali/hijri-date
Build Process & Challenges
Building the app in Xcode involved compiling the code, resolving errors and creating a distributable package. We set the minimum macOS version to 12 during this process.
App Icon
Creating a visually appealing icon was also important. We designed a custom icon and added it to Xcode in various sizes to ensure it adapts to different screen resolutions. We used this free online tool to achieve this https://www.candyicons.com/free-tools/app-icon-assets-generator.
Distribution
Distributing through traditional channels, such as the Mac App Store, requires a paid Apple Developer ID, so we chose to make it freely available on GitHub.
Contemplating further Features
While features like automatic launch at login were initially considered, the focus remained on core functionality and a simple user experience. Launch at login ensures the menu bar icon is always visible (i.e. the app is started after login/restart). However, instructions are provided to users during installation on manually setting launch at login.
Creating DMG File
To ensure smooth installation, we created a DMG file, using the create-dmg tool. This would guide users through the installation process. We crafted clear and concise instructions for users to drag the app to their Applications folder, and launch from there.
Conclusion
This journey, from concept to distribution, has been a valuable learning experience in macOS development. We hope to continuously improve the Hijri Menu Bar app and provide users with a seamless way to view Hijri dates on their Macs.
If you’re interested in trying out the app or contributing to its development, you can find it on GitHub (https://github.com/Enamulali/hijri-date).