Skip to content
Blog

Detecting iOS Simulators Reliably in Flutter with is_ios_simulator

Why environment detection matters for biometric, camera, and APNS push notification testing, and how is_ios_simulator simplifies simulator logic.

Published on • October 30, 2026

AI Assistant

When building iOS apps in Flutter, developers frequently need to branch their code depending on whether the app is executing on a physical iPhone or inside the macOS Xcode iOS Simulator.

Features such as Apple Push Notification service (APNS), camera capture, FaceID/TouchID biometrics, and Metal hardware acceleration exhibit subtle differences between physical silicon and x86_64/ARM64 virtualized simulators.

The lightweight package is_ios_simulator provides a clean, zero-overhead way to identify simulator execution.

Why device_info_plus Isn’t Always the Answer

While device_info_plus is the standard plugin for full hardware telemetry, fetching device info requires an asynchronous platform channel call:

// Heavyweight and requires awaiting asynchronous platform channels
final deviceInfo = DeviceInfoPlugin();
final iosInfo = await deviceInfo.iosInfo;
final isSimulator = !iosInfo.isPhysicalDevice;

If your app needs this check synchronously inside a dependency injection container (like GetIt) or during early startup before runApp() executes, asynchronous platform channels can introduce startup latency.

Instant Detection with is_ios_simulator

The is_ios_simulator package leverages compile-time environment flags and ultra-fast POSIX system inspection:

dependencies:
  is_ios_simulator: ^1.0.0

Practical Implementation

import 'package:flutter/material.dart';
import 'package:is_ios_simulator/is_ios_simulator.dart';

void configureServices() {
  if (isIosSimulator) {
    // Provide mocked biometric authentication
    setupMockBiometrics();
    print('Running on iOS Simulator: Mocking hardware peripherals');
  } else {
    // Configure production APNS and hardware camera
    setupProductionHardware();
  }
}

class BiometricPrompt extends StatelessWidget {
  const BiometricPrompt({super.key});

  @override
  Widget build(BuildContext context) {
    if (isIosSimulator) {
      return const Banner(
        message: 'SIMULATOR',
        location: BannerLocation.topStart,
        child: Text('Simulated FaceID Passed'),
      );
    }
    return const Text('Scan FaceID on Device');
  }
}

Common Use Cases

  1. Mocking Push Notifications: Xcode simulators historically lacked full background APNS VoIP channels.
  2. Camera Fallbacks: Automatically substituting file pickers when running on desktop simulator harnesses lacking physical camera sensors.
  3. In-App Purchase (StoreKit) Sandbox: Directing simulator environments to local StoreKit test configuration files.

Using targeted detection utilities keeps your test suites fast and your code structure tidy.