January 30, 2025
5 min read

Sync Cursor AI with Xcode Projects

Written by [object Object]

By Kevin Kern

Xcode relies on .xcodeproj files to manage everything. Files, groups, and build settings all live there. But here’s the catch: when you make changes outside of Xcode (like in VSCode or with Cursor AI), those changes don’t automatically appear in Xcode.

Say you add a Swift file in VSCode, Xcode won’t even notice. If you’re not careful, you’ll end up with mismatched files, broken references, or messy folder structures.

Let’s fix that! Here’s how to keep your files and project in sync, step by step.

1. Setting Up Swift in Cursor AI

Swift Extensions for Cursor

Before diving in, make sure Cursor AI fully supports Swift by installing these key extensions:

  • Swift Extension: Adds syntax highlighting, code completion, and navigation.

  • SwiftLint: Keeps your code clean and enforces Swift style guidelines.

  • CodeLLDB: Integrates LLDB for debugging Swift code.

Steps to Install:

  • Install the Swift Extension for Cursor.

  • Add SwiftLint to help enforce consistent Swift code styling.

  • Install CodeLLDB for a smooth debugging experience.

SwiftLint

While not strictly necessary, this tool helps enforce Swift style and conventions.

brew install swiftlint

CodeLLDB

This extension is for debugging Swift code. It integrates with LLDB to provide a rich debugging experience.

  • Install CodeLLDB.

Adding .cursorrules for Custom Instructions

With a .cursorrules file, you can give Cursor specific instructions to improve your coding workflow.

  • Create a file named .cursorrules in the root directory of your project.

  • Define how you want the AI to assist you with code, comments, or formatting.

Here’s an example of what you can add:

You are an expert in coding with Swift, SwiftUI. You always write maintainable code and clean code. Focus on the latest September 2024 versions of the documentation and features. Your descriptions should be short and concise. Don't remove any comments.

The full guide on how to create your own Cursorrules is available here.

SwiftUI Project Structure

The main folder contains a "Sources" folder with "App" for main files, "Views" divided into "Home" and "Profile" sections with their ViewModels, and "Shared" for reusable components and modifiers. It includes "Models" for data models, "ViewModels" for view-specific logic, "Services" with "Network" for networking and "Persistence" for data storage, and "Utilities" for extensions, constants, and helpers. The "Resources" folder holds "Assets" for images and colors, "Localization" for localized strings, and "Fonts" for custom fonts. Lastly, the "Tests" folder includes "UnitTests" for unit testing and "UITests" for UI testing.

SwiftUI UI Design Rules:

  • Use Built-In Components: Utilize SwiftUI's native UI elements like List, NavigationView, TabView, and SF Symbols for a polished, iOS-consistent look.

  • Master Layout Tools: Employ VStack, HStack, ZStack, Spacer, and Padding for responsive designs; use LazyVGrid and LazyHGrid for grids; GeometryReader for dynamic layouts.

  • Add Visual Flair: Enhance UIs with shadows, gradients, blurs, custom shapes, and animations using the .animation() modifier for smooth transitions.

  • Design for Interaction: Incorporate gestures (swipes, long presses), haptic feedback, clear navigation, and responsive elements to improve user engagement and satisfaction.

If you're unsure on how to work with Cursor, check out my step by step guide.

Keep Xcode and Cursor in Sync with XcodeGen

When you add or rename files in Cursor, Xcode doesn’t always get the memo. That’s where XcodeGen comes in.

XcodeGen regenerates your Xcode project to match your folder structure, so your references stay up to date and in sync.

Installing XcodeGen

If you have Homebrew, installation is easy:

brew install xcodegen

Create a Project Configuration File

XcodeGen relies on a project.yml file to define your project’s structure and targets.

Here’s a basic example to get you going:

name: MyZunderApp
options:
  bundleIdPrefix: com.zunderai
  deploymentTarget:
    iOS: 17.0
  xcodeVersion: "15.3"
  generateEmptyDirectories: true
  createIntermediateGroups: true

targets:
  MyZunderApp:
    type: application
    platform: iOS
    sources: [MyZunderApp]
    settings:
      base:
        SWIFT_VERSION: 5.10.1
        ENABLE_TESTABILITY: YES
    info:
      path: Sources/Info.plist
      properties:
        CFBundleShortVersionString: "1.0.0"
        CFBundleVersion: "1"
        UILaunchStoryboardName: LaunchScreen
        UIApplicationSceneManifest:
          UIApplicationSupportsMultipleScenes: true

schemes:
  MyZunderApp:
    build:
      targets:
        MyZunderApp: all
    run:
      config: Debug

configs:
  Debug: debug
  Release: release

Make sure to replace MyZunderApp with your project name.

Set Up Your Folder Structure

If the project.yml is like the following:

name: MyZunderApp

Then the project directory should look like this:

mkdir MyZunderApp

Generate Your Xcode Project

xcodegen generate

Automating Tasks for a Smoother Workflow

To avoid repeating manual steps, you can automate key commands like building, syncing, or running SwiftLint.

Create a tasks.json File

Create a new file in .vscode/tasks.json and add the following:

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Generate Xcode Project with XcodeGen",
      "type": "shell",
      "command": "xcodegen",
      "args": ["generate"],
      "problemMatcher": [],
      "group": {
        "kind": "build",
        "isDefault": true
      },
      "presentation": {
        "echo": true,
        "reveal": "always",
        "focus": false,
        "panel": "shared",
        "showReuseMessage": true,
        "clear": false
      },
      "runOptions": {
        "runOn": "folderOpen"
      }
    },
    {
      "label": "Build Swift Project",
      "type": "shell",
      "command": "xcodebuild",
      "args": [
        "-project", "todoapp.xcodeproj",
        "-scheme", "MyZunderApp",
        "-configuration", "Debug",
        "clean", "build"
      ],
      "problemMatcher": ["$xcodebuild"],
      "group": {
        "kind": "build",
        "isDefault": true
      },
      "presentation": {
        "echo": true,
        "reveal": "always",
        "focus": false,
        "panel": "shared",
        "showReuseMessage": true,
        "clear": false
      },
      "runOptions": {
        "runOn": "default"
      }
    }
  ]
}

Have a look at my article on how you can create projects faster with advanced prompt workflow techniques.

Bonus: Use SwiftLint to Keep Code Clean

If you haven’t already, follow these steps to integrate SwiftLint:

  • Install SwiftLint:

brew install swiftlint
  • Add a SwiftLint configuration file in your project directory (.swiftlint.yml).

  • Customize rules according to your needs.

Conclusion

By setting up Cursor AI with XcodeGen, SwiftLint, and automated tasks, you can keep your coding workflow smooth and consistent. Say goodbye to mismatched files and manual fixes—everything stays in sync, and you can focus on writing great code.

Check out my comparison of different AI tools you can use to help you along your journey.

Have a look at the rest of my Cursor guides:

- How to keep your code private with Cursor AI

- How to use Cursor with a large codebase

- 5 Cursor pro tips for rapid MVP development

- How to add custom documentation in Cursor AI

Happy coding!🚀