Skip to content

Releases: crimsondhakx/xcprune

Release list

v1.0.1

Choose a tag to compare

@crimsondhakx crimsondhakx released this 07 Sep 09:33

Fixes a false positive that affected any project localizing UI through XIBs or storyboards.

The bug

Xcode extracts a XIB's localizable strings into keys shaped <objectID>.<keyPath>, such as 0cO-dq-wRh.headerCell.title. The nib loader applies them by matching the object ID at load time, so the key is never written in source and has no generated symbol. Both matching strategies missed it, and live UI strings were reported as unused.

Measured against NetNewsWire:

v1.0.0 v1.0.1
Unused localization keys reported 39 4
of which were live XIB strings 35 0

If you ran v1.0.0 on a project with localized XIBs, treat its localization-key results as unreliable and re-run. Asset results were not affected.

The fix

Interface files now contribute their id="..." values, and a localization key counts as referenced when its leading dot-component matches a known object ID. Scoped narrowly: assets are not excused by a XIB object sharing a name, an ordinary dotted key like settings.title is still reported, and a key whose object ID appears nowhere is still reported.

Full detail in #4.

v1.0.0

Choose a tag to compare

@crimsondhakx crimsondhakx released this 02 Sep 09:30

Find unused images, colors, and localization keys in an Xcode project.

Every app accumulates dead resources — an image that outlived the screen using it, a localization key that outlived its copy — and Xcode never tells you. They ship in every download indefinitely.

Why another one

The existing tools for this were abandoned years ago, and none understand a modern project. Since Xcode 15 the compiler generates a Swift symbol per asset, so idiomatic code reads Image(.profileAvatar) and the asset name may never appear as a string literal at all. A tool that only greps for strings reports nearly the whole catalogue as unused, which is worse than no tool.

What counts as a use

  • the name as a string literal, Swift or Objective-C
  • the symbol Xcode generates, so Image(.profileAvatar) reaches profile_avatar
  • storyboard and xib attributes, so image="header" counts
  • Info.plist entries, so app icons and launch images count
  • implicit SwiftUI localization, so Text("welcome") reaches the key welcome

Reads asset catalogs including namespaced folders, and keys from .strings, .stringsdict, and the .xcstrings string catalog.

It never deletes

No static tool can be certain. UIImage(named: iconName) resolves at runtime, so any asset could be the one it loads. Where such a lookup exists xcprune names the file and line and marks that kind low confidence, rather than staying quiet and letting you delete shipping content.

A missed dead asset costs bytes. A false positive costs a blank screen in production. The bias is deliberate.

Use

xcprune                      # scan the current directory
xcprune --only localizationKey
xcprune --format json
xcprune --format github --fail-on-unused   # for CI

Complements periphery, which finds unused Swift code. No overlap.

Requires macOS 12 or newer. No external dependencies.