Visual Studio alternatives for Mac – finding a new home for MAUI development

Support for Visual Studio for Mac will end on August 31, 2024. So, which tools should MAUI developers use when Visual Studio for Mac is no more? We’ve compared JetBrains Rider, the .NET MAUI extension for VS Code, and the CLI approach!

app store

Introduction

Man, choosing a tool for developing cross-platform Xamarin apps on a Mac used to be so easy. Microsoft had our backs with Xamarin Studio, and later with Visual Studio for Mac.

Recently though, Microsoft decided to add a little twist!

Yes, the Xamarin MVP Monkey is giving us all a dramatic goodbye… 😢

Piano monkey

And Visual Studio for Mac is going with it. 🎹🎹 Yep, you heard that right: Visual Studio for Mac 17.6 will ride off into the sunset on August 31, 2024. 

Microsoft’s decision to retire the IDE isn’t unsurprising: The company is focusing on developing the .NET MAUI framework, the successor of Xamarin.Forms.

But fear not, dear developers, because Microsoft has a plan. 😉

They’re doubling down on Visual Studio Code as the go-to coding tool for Mac users. It’s like saying goodbye to your trusty old car and hopping into a shiny new rocket ship! 

But there are other options that might just become your preferred development environment. So in this article, we’ll explore these options. 

Also, if you haven’t checked out our guide for migrating Xamarin.Forms applications to MAUI yet, we recommend you take a look to ensure a smooth migration journey.

So strap in folks, because the MAUIverse is calling. 🚀

MAUI on Mac: your options

Alright, it’s time to check out the tools!

We’ll be covering three viable options for developing our .NET MAUI applications:

  1. The .NET MAUI extension in Visual Studio Code for Mac
  2. JetBrains Rider for Mac
  3. Using the command line tools on Mac (with an editor of your choice)

In this post, we’ll look at how to set up all options, their usage, and their pros and cons. After all, with great tools comes great responsibility (and maybe a few bugs too!).

In particular, we’ll go through the following for each option:

  • Installation
  • Creating a new project
  • Running and debugging
  • Using the NuGet package manager

Let’s start with the .NET MAUI extension in Visual Studio Code, which is the option recommended by Microsoft.

.NET MAUI extension in Visual Studio Code

The .NET Multi-Platform App UI (MAUI) extension is the gateway to the MAUI realm for Visual Studio Code users on Mac. It comes with all the necessary tools for developing cross-platform apps.

With the ability to develop and debug your creations on various devices, emulators, and simulators directly within VS Code, Microsoft aims to replicate the seamless experience of Visual Studio for Mac.

The .NET MAUI extension is built on top of the powerful C#, C# Dev Kit and .NET Install Tool extensions, which gives you:

  • IntelliSense
  • An intuitive solution explorer
  • Package management and project references
  • Debugging
  • Unit tests
  • …and more!

💡 Installing the VS Code .NET MAUI extension also automatically installs the C#, C# Dev Kit and .NET Install Tool extensions as dependencies.

⚠️ Keep in mind that the .NET MAUI extension is still in preview. It therefore has some limitations and kinks to work out.

C# Dev Kit and C# extensions

C# Dev Kit is an extension designed to enhance your coding experience. Among other things, it gives you a solution explorer to navigate your code in the IDE as well as integrated unit test discovery and execution to ensure your code is test-driven.

This extension builds on the powerful C# language capabilities provided by the C# extension. C# Dev Kit’s tools and utilities integrate natively with VS Code and help developers to write and debug code faster, to avoid errors, and to simplify maintenance.

💡 C# Dev Kit is free for individuals, academia, and open-source development. For organizations, it’s included with Visual Studio Professional and Enterprise subscriptions.

Installation

Visual Studio Code is a lightweight but powerful source code editor. It comes with built-in support for JavaScript, TypeScript and Node.js and has a rich ecosystem of extensions for other languages and runtimes (such as C++, C#, Java, Python, PHP, Go, .NET).

  • Download VS Code and install it.
  • Download .NET and install it (make sure you download the right file for Apple Silicon machines).
  • In Visual Studio Code, install the .NET MAUI extension. This will also install C#, C# Dev Kit and .NET Install Tool as dependencies.
Installing the .NET MAUI extension in Visual Studio Code
Installing the .NET MAUI extension in Visual Studio Code

For iOS/macOS development:

  • We need to install Xcode for its SDK and simulators. Downloading Xcode requires an Apple ID.
  • Download and install Xcode.
  • Install the Xcode command line tools with the following command:

    xcode-select --install
     
  • Launch Xcode. On the first open it will ask you to set up the iOS Simulator, so let’s do that.

Your iOS setup is now ready to run on simulators. However, to run the app on your device, you will need a valid certificate and provisioning profile (you can find more information here).

For Android development: 

  • Install Microsoft OpenJDK 17. Older JDK versions can cause issues and are therefore not recommended.
  • During the installation, JDK will prompt you to install Rosetta (if not already installed).
  • After installing JDK, create a new project and install the Android SDK using the following command:

    sudo dotnet build -t:InstallAndroidDependencies
    -f:net8.0-android
    -p:AndroidSdkDirectory=/Users/MyLocalFolderName/Library/Android/sdk
    -p:JavaSdkDirectory=/Library/Java/sdk
    -p:AcceptAndroidSDKLicenses=True

    In this command, AndroidSdkDirectory specifies where to install the Android SDK (e.g., /Users/MyLocalFolderName/Library/Android/sdk) and JavaSdkDirectory where to install the Java SDK (e.g., /Users/MyLocalFolderName/Library/Java/sdk).

💡 Another approach is to use Android Studio to manage the SDK, APIs, tools, emulators, debug options, logs, etc. This requires some environment variable setup.

  • Restart VS Code and check out the Output tab, which gives you information about the Android and iOS/macOS SDK status.
  • Now you have to accept the license for your Android SDK.

    In VS Code, press Cmd + Shift + P, select “.NET MAUI: Configure Android”, and you should get an option to accept the license. Alternatively, restart your project, and you’ll be prompted to accept the license via the command line.
  • Set the JDK and Android SDK paths as well. In VS Code, press Cmd + Shift + P and select the option “.NET MAUI: Configure Android”

Now you should be able to run it on your Android device.

  • Finally, we need to install the .NET MAUI workloads with the following command:

    dotnet workload install maui

Creating a new project

We will create our first Visual Studio Code demo application using the .NET MAUI extension as follows:

  • Click the Create .NET Project button or press Cmd + Shift + P 
  • Select .NET: New Project
  • Select the project template .NET MAUI App
  • Select a project directory
  • Enter the project name and submit
  • Confirm Create Project
Creating a new project with the .NET MAUI extension
Creating a new project in VS Code using the .NET MAUI extension
  • If your project gets a build time error regarding the .NET MAUI tools, use the following command to install the necessary workloads:

    dotnet workload restore

Running and debugging

  • On the bottom toolbar in Visual Studio Code, you will see the toolbar item  “{ }” .
    With this, you can check the current target configuration.
  • Through the  “{ }”  button, you can also update the startup project and the target device options.
  • After selecting the configurations, you can simply press F5 to run the project. You can also open the RUN AND DEBUG tab from the side panel of VS Code and click on the Run and Debug button.
  • Debugging is similar to what we had in Visual Studio for Mac, like setting the breakpoints in the code.
  • Changing the configuration from Debug to Release mode isn’t supported yet. However, you can do that by adding a custom configuration in a launch.json file. After adding these configurations, you can use them from the RUN AND DEBUG tab.

    The launch.json file is created locally in the .vscode folder. Here is what the configurations look like:

    "configurations": [
        {
            "name": "Developer",
            "type": "maui",
            "request": "launch",
            "configuration": "Debug",
            "preLaunchTask": "maui: Build"
        },
        {
            "name": "Production",
            "type": "maui",
            "request": "launch",
            "configuration": "Release",
            "preLaunchTask": "maui: Build"
        }
      ]
Running and debugging with the .NET MAUI extension
Running and debugging in VS Code

Package management & project reference

NuGet package manager:

Visual Studio Code doesn’t really have a full-fledged NuGet package manager GUI like Visual Studio for Mac does. But there are some alternative options.

Restoring the packages:

  • You can set Automatic NuGet restore to ON. VS Code will now restore the packages automatically if the project is missing them.

    Visual Studio Code -> Settings -> Extensions -> C# -> LSP Server -> Dotnet -> Enable Automatic Restore

    Alternatively, go to Visual Studio Code -> Settings and search for the following text: ”dotnet.projects.enableAutomaticRestore”

    This is the option we’re looking for:
Enable Automatic Restore
“Enable Automatic Restore”
  • The other option is to use the command line to restore the packages. We’ll look at this in the next section.
  • To change or update the NuGet source, you have to modify the Nuget.Config file directly, which you can find at /Users/<username>/.config/NuGet.Config.

Adding NuGet packages and project references:

Adding, removing, and updating packages is easy. It’s not like the NuGet package manager window in Visual Studio for Mac, but it does the job. 

  • To add a NuGet package or a project reference, go through the Solution Explorer context menu like so:

    VS Code File Explorer -> Solution Explorer -> Expand Solution -> Right Click on the project
Adding a NuGet package or project reference in VS Code
  • To remove/update a NuGet package, you can expand the project dependencies and navigate to the exact package.
  • To remove a project reference, you have to directly edit the .csproj file, e.g.:

    <ItemGroup>
        <ProjectReference Include="..\..\FirstClassLibrary.csproj" />
    </ItemGroup>

JetBrains Rider

I believe this GIF adequately portrays Rider’s power. But will you be able to handle it?

JetBrains Rider is a full-fledged cross-platform .NET IDE providing a complete environment for developing .NET MAUI apps.

Rider works with a wide variety of .NET Framework, Mono, and .NET Core project types. It supports most languages used in .NET development, including C#, VB.NET, F#, ASP.NET syntax, XAML, XML, JavaScript, TypeScript, JSON, HTML, CSS, and SQL. Its large set of powerful features that also work across different languages lets you deliver quality code faster than ever.

All this makes it the best choice for replacing Visual Studio for Mac.

One important thing to note, however, is that JetBrains Rider requires a paid subscription.

Highlights:

  • More stable and reliable compared to Visual Studio for Mac.
  • Eliminates a lot of the annoyances of developing .NET MAUI apps in Visual Studio for Mac.
  • A full-fledged IDE, unlike the .NET MAUI extension for VS Code.
  • The decompiler allows you to jump directly into the third-party package/code in your project, even from a particular XAML class implementation (e.g., Label).
  • Powerful IntelliSense code completion, refactoring, debugging, version control and more.
  • Convenient shortcuts that increase productivity, a bunch of different IDE settings, and more.

Installation

  • Download JetBrains Rider here and follow the general macOS application installation process.
  • For iOS/macOS development, we must install Xcode.
  • For Android, we need to install Microsoft OpenJDK 17 and Android Studio.

Initial JetBrains Rider settings

For Android development:

  • After installing Android Studio to get the Android SDK, launch JetBrains Rider.
  • Install the Rider Android Support plugin to get started with Android:

    JetBrains Rider -> Settings -> Plugins -> Install "Rider Android Support"
     
  • After installing this plugin, a new tab will show up in the JetBrains Rider settings:

    JetBrains Rider -> Settings -> Build, Execution, Deployment -> Android

    Here, set the paths for the Android SDK and the Microsoft Open JDK 17.

Make sure the developer options are enabled on your Android device. This completes the setup for Android development, so your app is ready to roll on your device.

You also have the option to create and launch an emulator from Android Studio.

For iOS development:

  • Install Xcode, then launch it to download/install the iOS simulators.
  • Now launch JetBrains Rider and set the Xcode path:

    JetBrains Rider -> Settings -> Build, Execution, Deployment -> Apple Platforms

After doing this, your iOS setup is complete, and your iOS app is also ready to roll on the simulator. To run the app on your iOS device, however, you will need a valid certificate and provisioning profile (you can find more information here).

Alright! Then let’s dive into creating a new application with Rider.

Creating a new project

Creating a new project is similar to Visual Studio for Mac: Just create a solution and select a project template.

Creating a new project in JetBrains Rider
Creating a new project in JetBrains Rider

Running and debugging

In Rider, there are separate sections for selecting a platform configuration, be it Android or iOS. The device and simulator/emulator lists are populated depending on the platform.

Device and simulator/emulator lists in Rider
Device and simulator/emulator lists in Rider

For debugging, select the debug button in the bottom left of the IDE window. 

Debugging in Rider

NuGet package manager

Rider integrates a simple interface for the NuGet package manager. It provides a good interface for search filters, adding/selecting custom sources, and logs, installation of packages for multiple projects at once, and more.

You can also right-click on the project and select Manage NuGet package, which will open this tab at the bottom.

Managing NuGet packages in Rider
Managing NuGet packages in Rider

The buttons on the left allow you to restore/download, update, refresh packages and much more.

.NET CLI on Mac

For the elite developers who prefer flexing their CLI muscle over relying on fancy IDE magic and crave results based solely on their precise inputs rather than any third-party influence, we raise a digital salute. 🫡

I call those people Terminal Ninjas. With unwavering confidence in their commands, they bend the CLI to their will. If you’re among them: Kudos! Let’s get started.

Choosing the terminal

Just like the other options, this one also has its pros and cons. It might take a bit of R&D until you find all the necessary commands needed for your development process.

Installation

  • Download the .NET SDK here and install it.
  • Install the .NET MAUI workload by using this command in the terminal (with or without sudo, depending on your privileges):

    dotnet workload install maui
     
  • To verify the workload installation, use the following command:

    dotnet workload list

For developing iOS/macOS and Android applications, we need to do the following:

  • For iOS/macOS development, install the Xcode tool for SDK and simulators.
  • For Android development, install the Microsoft OpenJDK and Android Studio for the Android SDK and emulators.

For the individual iOS and Android setup steps, please refer to the .NET MAUI extension section above.

Creating a new project

Let’s jump into all the core commands you’ll need: 

  • For creating a new project, the basic command is:

    dotnet new maui

    Here, maui is the template for MAUI projects. Typically, you’ll do this after some basic preparation, like creating a directory for the project:

    mkdir FirstCLIApp
    cd FirstCLIApp
    dotnet new maui

This series of commands creates a new project based on the template maui in the directory name FirstCLIApp. So by default your solution will be created as FirstCLIApp.sln, which will have a MAUI project named FirstCLIApp.csproj.

  • For setting a project name, use the following command:

    dotnet new maui -n "FirstCLIApp"
     
  • To check out all available project templates for a project, you can use this command:

    dotnet new list

For more parameters you can use while creating a project, see below. You can find further details in the Microsoft docs.

dotnet new <TEMPLATE>
    [--dry-run]
    [--force]
    [-lang|--language {"C#"|"F#"|VB}]
    [-n|--name <OUTPUT_NAME>]
    [-f|--framework <FRAMEWORK>]
    [--no-update-check]
    [-o|--output <OUTPUT_DIRECTORY>]
    [--project <PROJECT_PATH>]
    [-d|--diagnostics]
    [--verbosity <LEVEL>]
    [Template options]

Running and debugging

In this section, we will look at the commands related to restoring, building and running the project. For the full command reference, check out the .NET CLI docs.

  • Restore packages: Restores the dependencies and tools of a project.

    dotnet restore
     
  • Build: The following command will restore the project dependencies and build the app.

    dotnet build
        [<PROJECT>|<SOLUTION>]
        [-a|--arch <ARCHITECTURE>]
        [--artifacts-path <ARTIFACTS_DIR>]
        [-c|--configuration <CONFIGURATION>] 
        [-f|--framework <FRAMEWORK>]
        [--disable-build-servers]
        [--force] [--interactive] 
        [--no-dependencies] 
        [--no-incremental]
        [--no-restore] 
        [--nologo] 
        [--no-self-contained] 
        [--os <OS>]
        [-o|--output <OUTPUT_DIRECTORY>]
        [-p|--property:<PROPERTYNAME>=<VALUE>]
        [-r|--runtime <RUNTIME_IDENTIFIER>]
        [--self-contained [true|false]] 
        [--source <SOURCE>]
        [--tl:[auto|on|off]] 
        [--use-current-runtime, --ucr [true|false]]
        [-v|--verbosity <LEVEL>] 
        [--version-suffix <VERSION_SUFFIX>]

     
  • Run: The following command will restore the project dependencies and build the app.

    dotnet run 
        [-a|--arch <ARCHITECTURE>] 
        [-c|--configuration <CONFIGURATION>]
        [-f|--framework <FRAMEWORK>] 
        [--force] [--interactive]
        [--launch-profile <NAME>] 
        [--no-build]
        [--no-dependencies] 
        [--no-launch-profile] 
        [--no-restore]
        [--os <OS>]
        [--project <PATH>]
        [-r|--runtime <RUNTIME_IDENTIFIER>]
        [--tl:[auto|on|off]]
        [-v|--verbosity <LEVEL>]
        [[--] [application arguments]]

We can run the above commands without any parameters, but that sets them to their default values, which aren’t always what we need. So let’s jump into some use cases.

iOS simulator:

dotnet build
    -t:Run // target
    -f net8.0-ios // framework
    -p:_DeviceName=:v2:udid=<MY_SPECIFIC_UDID> // property

Here, the .NET MAUI iOS app is launched on a particular simulator by passing the simulator’s unique identifier. There are two ways to get the identifier:

Using Xcode:

Xcode -> Windows -> Devices and Simulators -> Right-click on the simulator -> Copy Identifier

Or using the command line (the following command prints all the devices in the terminal along with their identifiers):

/Applications/Xcode.app/Contents/Developer/usr/bin/simctl list

iOS device:

With the developer mode enabled on your iPhone or iPad, use the following command:

dotnet build
    -t:Run // target
    -f net8.0-ios // framework
    -p:RuntimeIdentifier=ios-arm64 // property
    -p:_DeviceName=<MY_SPECIFIC_UDID> // property

You can retrieve the device identifiers in the same way as the simulator identifiers.

Android emulator/device:

The following command works for both devices and emulators. If you use a device, make sure that developer mode is enabled.

dotnet build 
    -t:Run // target
    -f net8.0-android // framework

Finally, on the topic of debugging: When using the command line, debugging gets more complicated. It’s a huge topic that deserves an article of its own, so we won’t cover it here.

NuGet package manager

These are the commands used frequently to manage NuGet packages:

  • Restore the packages and tools for the project:

    dotnet restore | dotnet restore <PROJECT_FILE>
     
  • Clear the local NuGet cache:

    dotnet nuget locals all --clear
     
  • Add/remove a package:

    dotnet remove [<PROJECT>] package <PACKAGE_NAME>

    dotnet add [<PROJECT>] package <PACKAGE_NAME>
        [-f|--framework <FRAMEWORK>]
        [--interactive]
        [-n|--no-restore]
        [--package-directory <PACKAGE_DIRECTORY>]
        [--prerelease]
        [-s|--source <SOURCE>]
        [-v|--version <VERSION>]

There are many other important aspects, such as adding/removing/updating/disabling a custom source.

  • Add a NuGet source:

    dotnet nuget add source <PACKAGE_SOURCE_PATH>
        [--name <SOURCE_NAME>]
        [--username <USER>]
        [--password <PASSWORD>]
        [--store-password-in-clear-text]
        [--valid-authentication-types <TYPES>]
        [--configfile <FILE>]

     
  • Remove a NuGet source:

    dotnet nuget remove source <NAME> [--configfile <FILE>]
     
  • Enable or disable a NuGet source:

    dotnet nuget disable source <NAME> [--configfile <FILE>]

    dotnet nuget enable source <NAME> [--configfile <FILE>]

     
  • Update a NuGet source:

    dotnet nuget update source <NAME>
        [--source <SOURCE>]
        [--username <USER>]
        [--password <PASSWORD>]
        [--store-password-in-clear-text]
        [--valid-authentication-types <TYPES>]
        [--configfile <FILE>]

     
  • Display a list of all available NuGet sources. It reads from the global Nuget.Config file:

    dotnet nuget list source

Short comparison

Based on our own usage, we would like to provide feedback for the tools discussed in this article. As the command line approach is not a tool per se, we will only compare the .NET MAUI extension for Visual Studio Code and JetBrains Rider.

Rating factors.NET MAUI extensionJetBrains Rider
IntelliSense / editor★★★★★★★★★★
Solution explorer★★★★★★★★
Decompiler & navigation★★★★★★★
Running and debugging★★★★★★★★
Package manager★★★★★
Project ref. management★★★★★
Feature richness★★★★★★★★
Free of charge?✔️*

Elaboration on some points

Solution explorer:
The solution explorer in Rider offers more features and settings compared to the VS Code .NET MAUI extension. It’s also more interactive.

Running and debugging:
The run-and-debug experience in Rider is superior, with more configuration options and an easy-to-use interface. For example, you can see the list of simulators and devices separately, unlike in the VS Code .NET MAUI extension.

Decompiler & navigation:
One very helpful feature in Rider is that you can navigate to the class declaration directly, even if it is a third-party library. Other than that, code navigation is similar in both.

Package manager:
The package manager in the VS Code .NET MAUI extension is very basic: You can just add/update/remove a NuGet package. But inside Rider, you get a dedicated tool where you can add/update/remove NuGet packages as well as NuGet sources.

Project reference management:
Project reference management is very easy in Rider. If you’re using the VS Code .NET MAUI extension, you have to manually add and remove references.

Feature richness:
Rider is a full-fledged IDE, so it has many more features compared to the VS Code .NET MAUI extension.

Pricing:
Rider is paid software. The VS Code .NET MAUI extension depends on the C# Dev Kit extension, which is free for individual, academic, and open-source developers. Enterprises will need a Visual Studio Professional subscription.

Recommendation

We hope this comparison of the currently available Visual Studio alternatives for Mac helped you choose the best option for developing .NET MAUI applications.

We’d like to leave you with the following advice:

  • If you prefer a fully fledged, powerful IDE, go with JetBrains Rider. 
  • If you prefer to have a combination of a lightweight IDE and the CLI, then the .NET MAUI Extension in VS Code is your best bet. 
  • If you don’t want to rely on anything but your commands, then go with the CLI. However, this option still requires a good editor, which in most cases will be VS Code.

Good luck in selecting your approach and happy coding!

Developers, ready to get started?

Adding our free trial to your app is easy. Download the Scanbot SDK now and discover the power of mobile data capture