<!--
{
  "availability" : [
    "iOS: 26.0.0 -",
    "iPadOS: 26.0.0 -",
    "macCatalyst: 26.0.0 -",
    "macOS: 26.0.0 -",
    "tvOS: 26.0.0 -",
    "visionOS: 26.0.0 -",
    "watchOS: 26.0.0 -"
  ],
  "documentType" : "symbol",
  "framework" : "Foundation",
  "identifier" : "/documentation/Foundation/AttributedString/transformAttributes(in:body:)",
  "metadataVersion" : "0.1.0",
  "role" : "Instance Method",
  "symbol" : {
    "kind" : "Instance Method",
    "modules" : [
      "Foundation"
    ],
    "preciseIdentifier" : "s:10Foundation16AttributedStringV7SwiftUIE19transformAttributes2in4bodyyAD0B13TextSelectionVz_yAA18AttributeContainerVzxYKXEtxYKs5ErrorRzlF"
  },
  "title" : "transformAttributes(in:body:)"
}
-->

# transformAttributes(in:body:)

Apply a change to the attributes in the entire selection.

```
mutating func transformAttributes<E>(in selection: inout AttributedTextSelection, body: (inout AttributeContainer) throws(E) -> Void) throws(E) where E : Error
```

## Discussion

Applies the given `body` to the selection. Specifically, in the case of
a selection spanning one or multiple characters, the `body` is applied
to every run in the selection individually, modifying only the part of
the run that is in the selection.

In the case of an insertion point, the `body` is applied to the
attribute container defining the typing attributes. After that,
attributes that are bound to the whole paragraph or the character
immediately preceding the caret via
<doc://com.apple.documentation/documentation/Foundation/AttributedString/AttributeRunBoundaries>
are applied directly to attributed string at the respective range.

Use this function to implement controls that operate on the user’s
current selection. Some controls define the new value relative to the
current state of each individual run in the selection, e.g. a stepper
for the font size:

```
Stepper("Font Size", onIncrement: {
    text.transformAttributes(in: &selection) {
        $0.font = ($0.font ?? .default).scaled(by: 1.2)
    }
}, onDecrement: {
    text.transformAttributes(in: &selection) {
        $0.font = ($0.font ?? .default).scaled(by: 1 / 1.2)
    }
})
```

Other controls, such as toggles for boldness, italics, or underline
usually define the new value for all ranges as the opposite of the value
in the typing attributes, as defined by
`AttributedTextSelection/typingAttributes(in:)`:

```
Toggle("B", isOn: .init(get: {
    let font = selection.typingAttributes(in: text).font ?? .default
    return font.resolve(in: environment).isBold
}, set: { isBold in
    text.transformAttributes(in: &selection) {
        $0.font = ($0.font ?? .default).bold(isBold)
    }
}))
```

---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)