Skip to content

Make SwiftUI great again, on Neovim

Published: at 07:13 AM

Say goodbye to Xcode

For years, iOS and macOS developers have been tied to Xcode as their primary development environment. While Xcode is a powerful IDE with excellent debugging tools and interface builders, it comes with several limitations that can hinder productivity:

What if I told you there’s a way to develop SwiftUI applications with the speed, efficiency, and customization that Neovim offers? Let’s explore how to break free from Xcode’s constraints while maintaining full SwiftUI development capabilities.

Why Neovim

Neovim brings several advantages to SwiftUI development that make it a compelling alternative to Xcode:

Speed and Performance

Neovim is incredibly fast and lightweight. It starts instantly and doesn’t consume gigabytes of RAM like Xcode does. This means more resources for your builds and simulators.

Unmatched Customization

With Neovim, you can craft a development environment that’s perfectly tailored to your workflow. From key bindings to UI themes, everything can be customized to your preferences.

Language Server Protocol Support

Through LSP, Neovim can provide the same intelligent code completion, error detection, and navigation features you expect from modern IDEs.

Terminal Integration

Seamlessly run build commands, tests, and simulators directly from your editor without switching contexts.

Plugin Ecosystem

The vast ecosystem of Neovim plugins allows you to extend functionality far beyond what any single IDE can offer.

My setup and dot file

To get SwiftUI development working smoothly in Neovim, we’ll use LazyVim as our base configuration. Here’s the complete setup:

Step 1: Ensure sourcekit-lsp is Available

First, verify that sourcekit-lsp is available on your system. This language server is provided through Xcode:

xcrun --find sourcekit-lsp

If this command returns a path, you’re good to go. If not, make sure you have Xcode installed and the command line tools configured:

xcode-select --install

Step 2: Configure sourcekit-lsp in LazyVim

Since sourcekit-lsp isn’t supported by mason.nvim, we need to configure it manually. Create or edit ~/.config/nvim/lua/plugins/lsp.lua:

return {
  {
    "neovim/nvim-lspconfig",
    opts = {
      servers = {
        sourcekit = {
          cmd = { "xcrun", "sourcekit-lsp" },
          filetypes = { "swift", "objective-c", "objective-cpp" },
          root_dir = require("lspconfig.util").root_pattern("Package.swift", ".git"),
        },
      },
    },
  },
}

This configuration specifies:

Step 3: Additional Swift-specific Plugins

For an even better Swift development experience, consider adding these plugins to your LazyVim setup:

-- In your plugins directory
return {
  -- Swift syntax highlighting
  {
    "keith/swift.vim",
    ft = "swift",
  },

  -- Enhanced Swift support
  {
    "wojciech-kulik/xcodebuild.nvim",
    dependencies = {
      "nvim-telescope/telescope.nvim",
      "MunifTanjim/nui.nvim",
    },
    config = function()
      require("xcodebuild").setup()
    end,
  },
}

Last thing to make it work

Verify LSP Functionality

Open a Swift file and run :LspInfo to confirm that the sourcekit language server is attached and working properly. You should see sourcekit listed with its supported capabilities.

Configure Xcode Projects with compile_commands.json

For Xcode-based projects, sourcekit-lsp might not automatically understand your project structure. Here’s how to fix that:

Install xcode-build-server

brew install xcode-build-server

Generate Build Configuration

In your project root directory, run:

xcode-build-server config -project YourProject.xcodeproj -scheme "YourScheme"

Replace YourProject.xcodeproj and YourScheme with your actual project name and scheme.

Verify Build Server Configuration

Ensure the generated buildServer.json file contains the correct build_root path. This allows sourcekit-lsp to understand your project structure and provide accurate code completion and navigation.

Final Testing

Create a simple SwiftUI view to test everything is working:

import SwiftUI

struct ContentView: View {
    @State private var message = "Hello, Neovim!"

    var body: some View {
        VStack {
            Text(message)
                .font(.title)
                .padding()

            Button("Update") {
                message = "SwiftUI in Neovim rocks!"
            }
        }
    }
}

You should now have:

Conclusion

By setting up Neovim with sourcekit-lsp, you’ve created a powerful, customizable development environment for SwiftUI that rivals Xcode in functionality while surpassing it in speed and flexibility.

This setup gives you:

While you might still need Xcode occasionally for Interface Builder, simulators, or App Store submissions, you can now do the majority of your SwiftUI development in an environment that’s truly yours.

Welcome to the future of Swift development – fast, flexible, and completely customizable. Make SwiftUI great again, on Neovim!