From time to time, it might be a good idea to spend a couple of hours checking if there is some code in the codebase that is not being used anymore.
Luckily for us, there is a tool out there that can make the job easier.
Periphery: A tool to identify unused code in Swift projects.
Using Periphery on a project
If you want to use Periphery on your .xcodeproj
:
- Install it:
brew install peripheryapp/periphery/periphery
- Navigate to your project and set it up:
periphery scan --setup
- Select the project
- Select the build target
- Select the scheme
- Set your configuration options
- Save the configuration file
- The next time you can just run:
periphery scan
and it will use the same configuration previously saved.
As you can see, the tool found 1 property that is not being used:
Property 'hey' is unused
We can navigate to it and remove it.
Using Periphery on an SPM Package
Periphery uses swift build
to compile the code, so if your SPM package supports macos
, the process is exactly the same as for .xcodeproj
files.
However, if your package only supports iOS, there are some additional steps needed to make it work:
- Build the package using
xcodebuild
:- Provide the scheme name.
- Provide an iOS Simulator as the destination.
- Provide a path for the derived data.
xcodebuild -scheme UnusedCodeExamplePackage1 -destination 'platform=iOS Simulator,OS=16.4,name=iPhone 14' -derivedDataPath ~/Desktop/dd clean build
- Remember to change the name of the package.
- π‘ Additional tip: you could use this line if the Package and its folder use the same name:
xcodebuild -scheme "$(basename "$(pwd)")" -destination 'platform=iOS Simulator,OS=16.4,name=iPhone 14' -derivedDataPath ~/Desktop/dd clean build
- Set up periphery:
- Use
--skip-build
option. - Provide the path to the derived data folder.
periphery scan --skip-build --index-store-path ~/Desktop/dd/Index.noindex/DataStore/ --setup
- Set up the configuration file and save it.
- π‘ Additional tip: you could use this line if you donβt want to set up and save the configuration file:
periphery scan --skip-build --index-store-path ~/Desktop/dd/Index.noindex/DataStore/ --retain-public true --targets "$(basename "$(pwd)")"
- Use
- The next time you can just run:
periphery scan
.
Notes:
- Remember to delete the
dd
folder before pushing (only if you are using a destination inside your project) (or just use another destination for the derived data folder). periphery scan
will fail if the derived data folder does not exist, in that case, just run thexcodebuild
command again.
Bringing it all together in one method
For SPM packages, most of the times the name of the target is exactly the same as the name of the folder, so we can create a bash script and add it to the .zshrc
as a method:
1.
vim ~/.zshrc
2.
Add the following code:
deadcode() {
local folder_name="$(basename "$(pwd)")"
xcodebuild \
-scheme "$folder_name" \
-destination 'platform=iOS Simulator,OS=16.4,name=iPhone 14' \
-derivedDataPath ~/Desktop/dd \
clean build
periphery scan \
--skip-build \
--index-store-path ~/Desktop/dd/Index.noindex/DataStore/ \
--retain-public true \
--targets "$folder_name"
rm -rf ~/Desktop/dd
}
3.
Reload the ./zshrc
Now you can run deadcode
inside any SPM folder and wait for the results π.
Over the long run, keeping the code as clean as possible will be a benefit for everyone in the team, given less code means less time compiling, and unused code just adds unneeded noise to the codebase.
Are you using Periphery or something similar in your projects?