<!--
{
  "documentType" : "article",
  "framework" : "AppKit",
  "identifier" : "/documentation/AppKit/updating-views-automatically-with-observation-tracking-in-appkit",
  "metadataVersion" : "0.1.0",
  "role" : "article",
  "title" : "Updating views automatically with observation tracking in AppKit"
}
-->

# Updating views automatically with observation tracking in AppKit

Use Swift Observation and automatic tracking to update your views in response to model data updates.

## Overview

Swift <doc://com.apple.documentation/documentation/Observation> provides the <doc://com.apple.documentation/documentation/Observation/Observable> macro to mark your models for automatic change tracking. When you combine `Observable` models with AppKit, the system automatically watches for property changes and updates your views. You don’t need to manually invalidate anything — AppKit handles it for you.

AppKit provides methods in several objects where automatic observation tracking happens. In a view subclass, [`updateConstraints()`](/documentation/AppKit/NSView/updateConstraints()), [`layout()`](/documentation/AppKit/NSView/layout()), and [`draw(_:)`](/documentation/AppKit/NSView/draw(_:)) are examples of methods that automatically track any `Observable` properties you read, and AppKit updates your views when those properties change.

> Note: In macOS 15, the system doesn’t enable automatic observation tracking by default. To enable it, add the <doc://com.apple.documentation/documentation/BundleResources/Information-Property-List/NSObservationTrackingEnabled> key to your app’s information property list and set the key’s value to <doc://com.apple.documentation/documentation/Swift/true>.

### Update view properties automatically

The [`viewWillLayout()`](/documentation/AppKit/NSViewController/viewWillLayout()) method automatically tracks `Observable` properties and updates views when they change. For example, to show a message list with a status label that displays unread message information, start by creating an `Observable` model with the properties your view needs:

```swift
@Observable
class MessageModel {
    var showStatus: Bool
    var statusText: String
}
```

Then, use these properties in your view controller’s `viewWillLayout()` method:

```swift
override func viewWillLayout() {
    super.viewWillLayout()
    statusLabel.alphaValue = model.showStatus ? 1.0 : 0.0
    statusLabel.stringValue = model.statusText
}
```

When the view first appears, AppKit runs `viewWillLayout()` and tracks that you read `showStatus` and `statusText`. If either property changes later, AppKit automatically runs `viewWillLayout()` again to update the label.

You can also automatically track changes in a custom view using [`layout()`](/documentation/AppKit/NSView/layout()).

### Draw views automatically

AppKit automatically tracks any `Observable` properties you read inside your [`draw(_:)`](/documentation/AppKit/NSView/draw(_:)) override. When those properties change, AppKit invalidates and redraws the view.

This automatic tracking also covers any methods that [`draw(_:)`](/documentation/AppKit/NSView/draw(_:)) calls. This means that if you override drawing methods in a cell subclass, such as [`drawKnob(_:)`](/documentation/AppKit/NSSliderCell/drawKnob(_:)) and [`drawBar(inside:flipped:)`](/documentation/AppKit/NSSliderCell/drawBar(inside:flipped:)), AppKit also tracks those overrides.

For example, to draw a custom slider cell that responds to model changes, start by creating an `Observable` model with the visual properties your cell needs:

```swift
@Observable
class SliderAppearance {
    var knobColor: NSColor
    var trackColor: NSColor
}
```

Then, override the drawing methods in your [`NSSliderCell`](/documentation/AppKit/NSSliderCell) subclass and read from the model inside each override:

```swift
class CustomSliderCell: NSSliderCell {
    var appearance: SliderAppearance

    override func drawKnob(_ knobRect: NSRect) {
        appearance.knobColor.setFill()
        NSBezierPath(ovalIn: knobRect).fill()
    }

    override func drawBar(inside rect: NSRect, flipped: Bool) {
        appearance.trackColor.setFill()
        NSBezierPath(roundedRect: rect, xRadius: 2, yRadius: 2).fill()
    }
}
```

When [`drawKnob(_:)`](/documentation/AppKit/NSSliderCell/drawKnob(_:)) and [`drawBar(inside:flipped:)`](/documentation/AppKit/NSSliderCell/drawBar(inside:flipped:)) run, AppKit tracks that they read `knobColor` and `trackColor`. If either property changes later, AppKit automatically redraws the slider.

## See Also

[`-  viewWillLayout`](/documentation/AppKit/NSViewController/viewWillLayout())

Called just before the [`layout()`](/documentation/AppKit/NSView/layout()) method of the view controller’s view is called.

[`-  updateViewConstraints`](/documentation/AppKit/NSViewController/updateViewConstraints())

Called during Auto Layout constraint updating to enable the view controller to mediate the process.

[`-  drawRect:`](/documentation/AppKit/NSView/draw(_:))

Overridden by subclasses to draw the view’s image within the specified rectangle.

[`-  layout`](/documentation/AppKit/NSView/layout())

Perform layout in concert with the constraint-based layout system.

[`-  updateConstraints`](/documentation/AppKit/NSView/updateConstraints())

Update constraints for the view.



---

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)