Figment.so
Mac hostingWebsite hostingGuidesHow to usePricing

Simulate Poor Network Conditions for iOS Testing

Testing a networking layer on office Wi-Fi tells you almost nothing. Install Apple's Network Link Conditioner (NLC) from the Additional Tools for Xcode package on a hosted Mac, enable the Very Bad Network preset, and confirm your URLSession retry and timeout logic triggers against the iOS Simulator. For Xcode plus Simulator plus a remote-desktop session running together, a Figment M-series Mac starts at $95/month; physical i3 ($49/month) and M-series plans are request-based until supply is confirmed. The $29/month virtual Intel macOS tier runs compatible Intel Xcode (Xcode 26 or earlier per Apple's porting guide) and can host the iOS Simulator and NLC pane, but it has no GPU acceleration or audio and is accessed through a browser console, so throttling behavior there is best confirmed by running the Simulator on an M-series Mac or by agreeing the VM configuration in the quote first.

NLC is a macOS preference pane that throttles the host network stack with configurable bandwidth, latency and packet-loss settings. Because the iOS Simulator uses the host Mac's network, every NLC profile you apply affects the Simulator too — no device cables, no provisioning profiles.

NLC does not ship with Xcode by default. It lives in the Additional Tools for Xcode package on Apple's developer downloads site:

  1. In Xcode, pick Xcode → Open Developer Tool → More Developer Tools…. That opens the Apple developer downloads page (sign in with your Apple ID).
  2. Search for Additional Tools for Xcode and pick the version matching your installed Xcode.
  3. Mount the .dmg and open the Hardware folder. Inside is Network Link Conditioner.prefPane.

The download page works the same from the browser console on a hosted Mac — you just stay signed in to the Apple developer portal in Safari.

Installing the Preference Pane on the Hosted Mac

Connect using the access path agreed in your Figment quote (browser console on the $29 VM; agreed remote-desktop path on physical plans). Then:

  1. Open the mounted Hardware folder in Finder.
  2. Double-click Network Link Conditioner.prefPane. macOS asks whether to install for the current user or all users; pick the option that matches how you run the Simulator.
  3. Open System Settings → Network Link Conditioner (macOS Ventura and later) or System Preferences → Network Link Conditioner on older macOS. The pane appears at the bottom of the window.

If the pane doesn't appear, remove any stale copy from ~/Library/PreferencePanes/ and reinstall. On fresh macOS versions Apple occasionally gates third-party panes behind Privacy & Security; approve it once and re-open System Settings.

Built-in Presets and What They Simulate

NLC ships with five built-in presets. Read the exact numbers from the pane on your installed macOS — Apple has adjusted the defaults between releases — and use this table as the real-world mapping, not a precise spec sheet:

PresetApprox. down / up BWLossApprox. delayReal-world scenario
Edge240 / 200 Kbps0%400 / 440 msRural 2G fallback
3G780 / 330 Kbps0%~100 msIndoor 3G cell signal
LTE~50 / 50 Mbps0%~65 / 50 msClean LTE outdoors
Very Bad Network~1 / 1 Mbps~10%~500 msCongested café Wi-Fi
100% Loss—100%—Airplane mode / dead zone

Turn a preset ON in the pane; it takes effect on every connection the Mac makes, including your remote-desktop session. If VNC-style sessions start lagging, switch to LTE or disable NLC before navigating the desktop, then re-enable the target preset just before the test run.

Creating a Custom Profile

Click Manage Profiles… (or +, depending on macOS version) to add a scenario your production telemetry actually shows:

  • Downlink / uplink bandwidth — mobile upload is usually much slower than download; set them independently.
  • Downlink / uplink packet drop — percentages. 2–5% is a loaded cell; 10%+ is a failing link.
  • Downlink / uplink delay — one-way latency in milliseconds.
  • DNS delay — a fixed penalty per lookup. Useful for finding apps that make repeated DNS calls instead of caching.

A realistic "roaming abroad" profile: 1 Mbps down, 512 Kbps up, 5% loss, 350 ms each way, 200 ms DNS delay.

Checking the Simulator Reacts Correctly

Run your app in the iOS Simulator with a preset enabled and exercise one real network path. The example below is an unexecuted sketch — copy it into your own test target and point it at an endpoint you control, then run twice (NLC OFF, NLC Very Bad Network) and compare actual elapsed times and error paths:

import XCTest

final class NetworkConditionTest: XCTestCase {
    func testTimeoutAndRetryFire() async throws {
        // Use an endpoint you own; httpbin is illustrative only.
        let url = URL(string: "https://example.invalid/api/ping")!
        var request = URLRequest(url: url, timeoutInterval: 3.0)
        request.httpMethod = "GET"

        let start = Date()
        do {
            let (_, response) = try await URLSession.shared.data(for: request)
            let code = (response as? HTTPURLResponse)?.statusCode ?? -1
            print("ok status=\(code) elapsed=\(Date().timeIntervalSince(start))")
        } catch {
            // A timeout or NSURLErrorNetworkConnectionLost is the expected
            // branch under Very Bad Network. Assert your retry layer was
            // invoked (e.g. via an injected mock), not just that time passed.
            print("error=\(error) elapsed=\(Date().timeIntervalSince(start))")
            throw error
        }
    }
}

Two rules for this kind of test:

  • A failed build or failed request is not a performance datapoint. Compare successful responses to successful responses; log the error and let the test fail when the network path fails.
  • Assert on your own retry layer's behavior (counter, injected mock, log) rather than on elapsed wall time. Wall time under throttling is noisy.

Turn It Off, Then Verify

NLC stays on across reboots. Leave Edge or 100% Loss enabled and your next xcodebuild, brew or CI agent heartbeat will crawl.

  1. Open System Settings → Network Link Conditioner.
  2. Toggle OFF.
  3. Re-run a single request without a timeout guard and confirm normal latency.

Use only a documented control method for the installed conditioner. networksetup and scutil do not by themselves select Network Link Conditioner profiles. Restore the prior state after the test and verify connectivity. A shell trap is useful for normal exits but cannot recover from every process or machine failure.

Picking the Right Figment Plan

  • $29 virtual Intel macOS (2 vCPU, 8 GiB RAM, 80 GiB disk): fine for Xcode 26 or earlier, Simulator and NLC in a browser console. No GPU/audio, Intel only.
  • $49 i3 physical Intel Mac: request-based; good for Intel toolchains that need bare-metal behavior.
  • $95+ M-series Mac: request-based entry price; use it when you need ARM execution, newer Xcode, Metal/GPU work, or a smoother Simulator + remote-desktop experience. Exact chip, RAM and disk are confirmed in the quote — Figment's $95 entry is a lower starting price than many M4-class listings (for example CloudMac's $99.99/month M4/16 GB/256 GB plan, or MacStadium's M4.S at $149/month), but it is not a guaranteed equivalent M4 configuration.
  • $249 Managed Build Mac: one M-series Mac with CI setup, backups, monitoring and 30 minutes of monthly support.

Request a Mac configuration or get started on /mac-hosting/start.

Related guides:


Subscribe for Figma design and website publishing guides.


Figment.so

Contact

Twitter

Website pricing

Compute index

About

Privacy

Terms