AccessibilityIdentifier is a Swift macro that generates a type-safe namespace of accessibility identifiers from stored properties on a class or struct. It removes the need to manually keep string identifiers in sync and makes UI tests and audits more reliable.
- Swift 6.3 toolchain or later (tested with Xcode 27)
- Platforms: macOS 14, iOS 13, tvOS 13, watchOS 6, macCatalyst 13
- Automatic Identifier Generation: Generates static
Stringproperties for accessibility identifiers based on your stored properties. - Improved Testability: Provides a clear, type-safe way to reference accessibility identifiers in UI tests (e.g., using XCUITest).
- Reduced Boilerplate: Eliminates manual string declaration and potential for typos.
- Compile-Time Safety: Ensures identifiers are valid and consistent during compilation.
Add the AccessibilityIdentifier package to your Package.swift dependencies and include the product in your target:
dependencies: [
.package(url: "https://github.com/YOUR_USERNAME/swift-macro-accessibilityIdentifier.git", from: "1.0.0"),
],
targets: [
.target(
name: "YourApp",
dependencies: [
.product(name: "AccessibilityIdentifier", package: "swift-macro-accessibilityIdentifier"),
]
)
]Annotate a class or struct with @AccessibilityIdentifier. The macro will generate a nested Identifiers struct at compile time. This example is taken from the test fixture in this repo.
@AccessibilityIdentifier
class MyViewController: UIViewController {
var aButton: UIButton { UIButton() }
lazy var aTextField = UITextField()
let aLabel = UILabel()
}class MyViewController: UIViewController {
var aButton: UIButton { UIButton() }
lazy var aTextField = UITextField()
let aLabel = UILabel()
public struct Identifiers {
public static let namespace = "MyViewController"
public static let aButton = "MyViewController.aButton"
public static let aTextField = "MyViewController.aTextField"
public static let aLabel = "MyViewController.aLabel"
}
}You can now reference identifiers like:
view.accessibilityIdentifier = MyViewController.Identifiers.aButton- The macro must be applied to a
classorstruct. - Each stored property must use a simple identifier pattern (e.g.,
let foo = ...,var bar: Type,lazy var baz = ...).