Using built-in swift-format
for linting in Xcode 16 build phases
- 26 Oct, 2024
swift-format
has been included in the Swift Toolechain since Swift 6. It allows us to run it with swift format
command and eliminates the need to build or install swift-format
binary or manage different versions for each Swift release.1
Thanks to this integration, we can now use swift-format
in Xcode 16 as well. As shown in the cover image, you can format a file by selecting Editor > Structure > Format File with “swift-format” from the Xcode menu bar.
However, my goal during development is not just formatting, but linting the code during the build process.
In this post, I will explain how to run linting with swift format
and how to resolve a specific issue you might encounter.
How-to 1: Running the swift format
in a Run Script
Follow these steps to enable linting during th build process:
-
Select your project file, go to “Build Phases” and add a “Run Script” Phase. Move the newly added phase before “Compile Sources”.
-
Add the following command. In this case,
Sources
andTests
are the folders you want to lint.
That’s it! Simple, right?
The key point here is that you no longer need to manage things like the path to swift-format
, which was previously required.
However…there is one pitfall with this method!
The problem is that, in some cases, this setup doesn’t work at all. Worse yet, no errors occur during the linting phase, even though it works perfectly fine in Terminal.
After some investigation, I figured out that the issue is with the “User Script Sandboxing” setting in Build Settings of my project.
By setting this to NO
, the script perfectly works.
Since Xcode 15, the build setting, ENABLE_USER_SCRIPT_SANDBOXING=YES
, is set by default when creating projects. In Xcode 14 and before, this setting was not set, meaning it was implicitly set to NO as far as I confirmed.
But is it OK to leave it set to NO
? Is there a way to run linting while it’s still set to YES
?
Of course, there is. Adding a simple Xcode build tool plugin lets you achieve this.
Next, I’ll describe how to do that.
How-to 2: Using an Xcode Build Tool Plugin
- Add a Swift package to your project:
- Modify
swift_format_plugin.swift
as follows:
- Add this as a Local package in your Xcode project2, then go to Project > Build Phases > Run Build Tool Plug-ins and add
swift-format-plugin
target.
Now, linting will work even with User Script Sandboxing enabled!
Wrap up
Which method you choose depends on your project. In some cases, adding a plugin might feel excessive. On the other hand, you may want to keep sandboxing enabled due to security concerns.
Oh, you’re using SwiftFormat/SwiftLint
? Well, to each their own.
I hope this article helps with your app development.
Footnotes
-
swift-format: Included in the Swift Toolchain https://github.com/swiftlang/swift-format?tab=readme-ov-file#included-in-the-swift-toolchain ↵
-
Editing a package dependency as a local package https://developer.apple.com/documentation/xcode/editing-a-package-dependency-as-a-local-package ↵