Xcode 16 now comes with swift-format out of the box
Keep your Swift code clean and consistent with minimal effort
Introduction
Maintaining a consistent code style is one of those nice-to-haves, especially in a project with more than one contributor. With the release of Xcode 16, the swift-format library is now bundled. The only drawback — no autoformat on save. Thankfully, you can combine manual formatting with an automation using swift-format
in a Git pre-commit hook. This ensures that every time you commit code, your Swift files are automatically formatted.
In this guide, we’ll walk you through setting up a Git pre-commit hook to run swift-format
on your staged Swift files.
Manually Format Code in Xcode 16
Format your file with
Xcode -> Editor -> Structure -> Format File with ‘swift-format’
or use the hot key CTRL + SHIFT + I.
It can become tedious to hotkey your way into perfection…what if we combined this with an automated process?
Use a Pre-Commit Hook?
A pre-commit hook is a script that runs automatically before each commit. By integrating swift-format
into this hook, you:
- Automate Code Formatting: Eliminate the need to manually format code.
- Ensure Consistency: Maintain a uniform code style across your project.
- Save Time: Reduce code review feedback related to styling issues.
Setup Guide
Step 0: Ensure swift-format command is available
While the swift-format project confirms the availability of the tool via the Swift Toolchain, I installed the tool from brew so no other configurations were required.
brew install swift-format
Step 1: Navigate to Your Project’s Git Hooks Directory
Open your terminal and navigate to your project’s .git/hooks
directory:
cd /path/to/your/project/.git/hooks
Step 2: Create the Pre-Commit Hook Script
Create a new hook script (if one doesn’t already exist) named pre-commit
:
touch pre-commitCopy cotouch pre-commit
Step 3: Add the Formatting Script
Open the pre-commit
file in your preferred (if it’s not nvim are you even dev?) text editor and add the following script:
#!/bin/bash
echo "Running swift-format on staged Swift files..."
# Get list of staged .swift files
FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.swift$')
# Initialize an array to hold modified files
MODIFIED_FILES=()
for FILE in $FILES; do
if [ -f "$FILE" ]; then
# Get the SHA before formatting
SHA_BEFORE=$(git hash-object "$FILE")
# Format the file
swift-format format -i "$FILE"
# Get the SHA after formatting
SHA_AFTER=$(git hash-object "$FILE")
# If the SHAs are different, the file was modified
if [ "$SHA_BEFORE" != "$SHA_AFTER" ]; then
echo "Swiftly Formatted file: $FILE"
MODIFIED_FILES+=("$FILE")
# Add the file back to staging
git add "$FILE"
fi
fi
done
# Check if any files were modified
if [ ${#MODIFIED_FILES[@]} -gt 0 ]; then
echo ""
echo "The following files were modified by swift-format:"
for FILE in "${MODIFIED_FILES[@]}"; do
echo " - $FILE"
done
echo ""
else
echo "No files needed formatting; you're a rockstar."
fi
Script Breakdown:
- FILES Variable: Lists all staged Swift files.
- MODIFIED_FILES Variables: Collection of files that got the
swift-format -i
treatment - For Loop: Iterates over each file and formats it using
swift-format
. - Re-Adding Files: Adds the formatted files back to the staging area.
Step 4: Make the Script Executable
Change the script’s permissions to make it executable:
chmod +x pre-commit
Step 5: Test the Hook
Now, when you attempt to commit changes, the hook will automatically format your Swift files.
Example:
git add MyViewController.swift
git commit -m "Add new feature"
Expected Output:
Running swift-format on staged Swift files...
Swiftly Formatted file: MyViewController.swift
The following files were modified by swift-format:
- MyViewController.swift
Step 6: Verify the Changes
After the commit, you can verify that your Swift files have been formatted according to your swift-format
configuration.
Additional Tips
- Sync
swift-format
to Xcode’s formatting options: Ensure thatswift-format dump-configuration
is configured to match your project's editing and indentation settings to avoid potential conflicts. - Share the Hook: For team projects, consider sharing the
pre-commit
script with contributors.
BONUS: Prompt to inspect or accept automatic formatting:
Update your script to automatically accept the formatting or to abort the commit:
#!/bin/bash
echo "Running swift-format on staged Swift files..."
# Get list of staged .swift files
FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.swift$')
# Initialize an array to hold modified files
MODIFIED_FILES=()
for FILE in $FILES; do
if [ -f "$FILE" ]; then
# Get the SHA before formatting
SHA_BEFORE=$(git hash-object "$FILE")
# Format the file
swift-format format -i "$FILE"
# Get the SHA after formatting
SHA_AFTER=$(git hash-object "$FILE")
# If the SHAs are different, the file was modified
if [ "$SHA_BEFORE" != "$SHA_AFTER" ]; then
echo "Swiftly Formatted file: $FILE"
MODIFIED_FILES+=("$FILE")
# Add the file back to staging
git add "$FILE"
fi
fi
done
# Check if any files were modified
if [ ${#MODIFIED_FILES[@]} -gt 0 ]; then
echo ""
echo "The following files were modified by swift-format:"
for FILE in "${MODIFIED_FILES[@]}"; do
echo " - $FILE"
done
echo ""
# Try to prompt the user using /dev/tty
if [ -e /dev/tty ]; then
# Prompt the user for input
while true; do
# Read input from /dev/tty
read -p "Would you like to inspect the changes before commit [y/n(o I trust my formatter)]? " RESPONSE < /dev/tty
# Convert response to lowercase using 'tr'
RESPONSE=$(echo "$RESPONSE" | tr '[:upper:]' '[:lower:]')
if [ "$RESPONSE" == "y" ]; then
echo "Please review the changes before committing."
echo "Commit has been aborted."
exit 1 # Abort the commit
elif [ "$RESPONSE" == "n" ]; then
echo "You're a braver dev than I!"
exit 0 # Continue with the commit
else
# Send the prompt to /dev/tty
echo "Please enter 'y' or 'n'." > /dev/tty
fi
done
else
# Cannot prompt the user; proceed or abort based on your preference
echo "Cannot prompt for input (no /dev/tty available)."
echo "Proceeding with the commit by default."
exit 0
fi
else
echo "No files needed formatting; you're a rockstar."
fi
- We can now interact with the script and by pressing ’n’, we wholesale trust the swift-formatter, just like any good swift fanboy.
Conclusion
While hotkeys can make you perfectly formatted, by setting up a Git pre-commit hook, you automate the whole thing. This ensures that every commit adheres to your project’s style guidelines, making code reviews smoother and your codebase cleaner.
Happy coding! and checkout my
follow on X @kingskodedev!