# How status_bar.py Controls the iOS Simulator Status Bar for Automated Testing

> Learn how status_bar.py controls the iOS Simulator status bar for automated testing. Programmatically set time, battery, and network indicators for deterministic UI tests.

- Repository: [Conor/ios-simulator-skill](https://github.com/conorluddy/ios-simulator-skill)
- Tags: how-to-guide
- Published: 2026-02-27

---

**The [`status_bar.py`](https://github.com/conorluddy/ios-simulator-skill/blob/main/status_bar.py) script provides a Python wrapper around the `xcrun simctl status_bar` command, enabling programmatic control of the iOS Simulator's status bar elements including time, battery level, and network indicators for deterministic UI testing.**

The `conorluddy/ios-simulator-skill` repository includes a dedicated utility for manipulating the visual state of the iOS Simulator's status bar. By encapsulating Xcode's `simctl` tool in a reusable Python module, [`status_bar.py`](https://github.com/conorluddy/ios-simulator-skill/blob/main/status_bar.py) allows test suites to establish consistent, repeatable visual conditions without manual intervention.

## Core Architecture of the Status Bar Controller

### Automatic Device Targeting via resolve_udid

At line 15 of [`ios-simulator-skill/scripts/status_bar.py`](https://github.com/conorluddy/ios-simulator-skill/blob/main/ios-simulator-skill/scripts/status_bar.py), the script imports `resolve_udid` from the shared device utility module ([`scripts/common/device_utils.py`](https://github.com/conorluddy/ios-simulator-skill/blob/main/scripts/common/device_utils.py)). This helper automatically detects the currently booted simulator when no explicit UDID is provided, ensuring seamless integration in CI environments where device IDs may vary between runs.

### The StatusBarController Class

The `StatusBarController` class (defined at line 18) serves as the primary interface for status bar manipulation. It initializes with a target device UDID stored as `self.udid` and exposes two high-level methods: **`override()`** for applying custom states and **`clear()`** for restoring defaults.

### Predefined Configuration Presets

Lines 21-51 define a **`PRESETS`** dictionary containing ready-made configurations such as `"clean"`, `"testing"`, `"low_battery"`, and `"airplane"`. These presets map to specific parameter combinations, allowing rapid application of common testing scenarios without manually specifying individual flags.

## Command Construction and Execution

### Building the xcrun simctl Command

The `override()` method constructs the base command list starting with `["xcrun", "simctl", "status_bar"]` at line 82. It appends the target UDID (defaulting to `"booted"` if none specified at lines 84-88) followed by the `override` sub-command at line 89. Optional arguments—including `--time`, `--dataNetwork`, `--wifiMode`, `--batteryState`, and `--batteryLevel`—are conditionally appended only when supplied (lines 92-101).

### Executing with Subprocess

The assembled command executes via `subprocess.run(..., check=True)` at lines 104-107. This approach raises an exception on command failure while returning `True` on success, providing clear feedback for test assertions and preventing silent failures in automation pipelines.

### Clearing Overrides

The `clear()` method (lines 116-124) mirrors the override construction logic but utilizes the `clear` sub-command instead. Executed similarly via subprocess (lines 125-129), this method restores the status bar to its default system-driven state, which is essential for test isolation and cleanup procedures.

## Practical Usage Patterns

### Command-Line Interface Options

The `main()` function (starting around line 132) parses arguments for preset selection, individual status bar flags, explicit UDID specification, and clearing operations. It resolves the target device through `resolve_udid` (lines 84-87) before invoking the appropriate controller method with either a preset dictionary or raw CLI parameters (lines 94-146).

### CLI Examples

Apply a preset configuration:

```bash
python scripts/status_bar.py --preset clean

```

Apply custom parameters directly:

```bash
python scripts/status_bar.py \
    --time 12:00 \
    --data-network 4g \
    --wifi-mode searching \
    --battery-state discharging \
    --battery-level 30

```

### Programmatic Integration in Test Suites

For Python-based testing frameworks, import the controller directly:

```python
from ios_simulator_skill.scripts.status_bar import StatusBarController
from ios_simulator_skill.scripts.common.device_utils import resolve_udid

udid = resolve_udid(None)
controller = StatusBarController(udid)

# Apply deterministic state before screenshot capture

controller.override(**StatusBarController.PRESETS["testing"])

# Execute UI tests...

# Restore defaults during teardown

controller.clear()

```

## Summary

- [`status_bar.py`](https://github.com/conorluddy/ios-simulator-skill/blob/main/status_bar.py) wraps `xcrun simctl status_bar` in a Pythonic API for the `conorluddy/ios-simulator-skill` project
- The `StatusBarController` class provides `override()` and `clear()` methods for state manipulation and restoration
- Built-in presets enable rapid configuration for common testing scenarios like "clean" screenshots or low battery conditions
- Automatic UDID resolution via `resolve_udid` simplifies CI/CD integration by targeting the booted simulator automatically
- Both CLI and programmatic interfaces support deterministic visual testing workflows through subprocess execution with strict error checking

## Frequently Asked Questions

### What specific status bar elements can status_bar.py control?

According to the source code in `conorluddy/ios-simulator-skill`, the script controls time display, cellular data network type (3G, 4G, LTE), Wi-Fi mode and signal strength, battery state (charging/discharging), and battery level percentage. These parameters map directly to the `--time`, `--dataNetwork`, `--wifiMode`, `--wifiBars`, `--batteryState`, and `--batteryLevel` flags of the underlying `simctl` command.

### How does the script handle multiple running simulators?

When multiple simulators are active, [`status_bar.py`](https://github.com/conorluddy/ios-simulator-skill/blob/main/status_bar.py) relies on the `resolve_udid` helper imported from [`scripts/common/device_utils.py`](https://github.com/conorluddy/ios-simulator-skill/blob/main/scripts/common/device_utils.py). If no explicit UDID is provided via command-line arguments, this utility automatically targets the currently booted simulator. For specific device targeting, users can pass a UDID directly to the `StatusBarController` constructor or via the `--udid` CLI flag.

### Can status_bar.py restore the default status bar appearance?

Yes. The `StatusBarController` class includes a dedicated `clear()` method (implemented at lines 116-129) that invokes the `xcrun simctl status_bar clear` command. This removes all programmatic overrides and returns the status bar to its default system-driven state, which is essential for maintaining test isolation and preventing state leakage between test cases.

### Is subprocess execution safe for automated test pipelines?

The implementation uses `subprocess.run()` with `check=True`, which ensures that any failure in the underlying `simctl` command raises a `CalledProcessError` immediately. This fail-fast behavior prevents silent failures in CI pipelines, while the Boolean return values from `override()` and `clear()` facilitate straightforward assertion logic in test frameworks.