---
title: 'Simulator and Device'
source: 'https://academia.sh/en/courses/ios-platform-and-tools/simulator-and-device'
course: 'iOS Platform and Tools'
language: en
updated: '2026-10-21T05:03:10+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Measures that the meeting is rejected when a capability the app requires is absent from the simulator'
    - 'Shows the capabilities the simulator and the device share as an intersection'
    - 'Measures that a simulated location replaces the real location'
    - 'Shows that the model counts capabilities and does not measure performance'
---

# Simulator and Device

Measuring a capability the app requires being absent from the simulator, the capabilities the simulator and the device share, and a simulated location replacing the real one.

The previous lesson brought the version constraints of packages together. Where the built app will run is a separate question. During development the app mostly runs in a **simulator**: an environment that runs on the computer and imitates a device. A real **device** carries its own hardware. Both run the same code, but they do not offer the same capabilities.

The measurement axis is the same: when two definitions meet, how is it resolved? In this lesson one definition is the capabilities the app requires, and the other is the capabilities an environment offers. A capability here carries a name: camera, location, network, motion sensor.

## The Classifier

```swift
// Meeting.swift — classifies how two definitions are resolved when they meet
struct Meeting {
    let label: String
    let first: Set<String>
    let second: Set<String>
    let result: Set<String>?

    init(_ label: String, first: Set<String>, second: Set<String>, result: Set<String>?) {
        self.label = label
        self.first = first
        self.second = second
        self.result = result
    }

    var resolution: String {
        if first.isEmpty || second.isEmpty
            || first.isSubset(of: second) || second.isSubset(of: first) {
            return "out-of-scope"
        }
        guard let result, !result.isEmpty else { return "rejection" }
        if result == first.union(second) { return "union" }
        if result == first.intersection(second) { return "intersection" }
        if result == first || result == second { return "precedence" }
        return "off-rule"
    }

    static func list(_ values: Set<String>) -> String {
        values.isEmpty ? "empty" : values.sorted().joined(separator: ",")
    }

    func report() {
        let outcome = result.map(Meeting.list) ?? "none"
        print("\(label): first \(Meeting.list(first)) | second \(Meeting.list(second)) | result \(outcome) -> \(resolution)")
    }
}

func summarize(_ meetings: [Meeting]) {
    for resolution in ["precedence", "intersection", "union", "rejection"] {
        let count = meetings.filter { $0.resolution == resolution }.count
        print("\(resolution): \(count)")
    }
}
```

## Differences and Limitations

The difference between the simulator and the device is a difference of the environment the code runs in, not of the code. The same built app runs in two places, but the machine underneath is not the same. The simulator runs on the development computer as a process: it uses the computer's processor, memory and network connection. The device is a separate machine with its own processor, limited memory, battery and thermal limit. For this reason a screen that looks smooth in the simulator can stutter on the device, and an operation that ends without trouble in the simulator can be terminated under memory pressure on the device.

It helps to divide the differences into three classes.

- **Hardware difference:** The simulator is an imitation of hardware. Hardware-bound capabilities such as the camera, the motion and orientation sensors, the vibration motor, biometric verification and wireless connection units are either not offered at all or are imitated with values the developer supplies by hand.
- **Environment difference:** The network, the file system and permission flows look the same in the two environments but do not run under the same conditions. The simulator uses the computer's fast and stable connection; the device may be on a weak, intermittent or metered connection.
- **Lifecycle difference:** On the device the user puts the app in the background, locks the device, switches to another app, receives a call. In the simulator these events can be triggered, but they do not occur on their own, so the developer often forgets to try them.

A limitation can be the absence of a capability, but it can also be a misleading presence. In the simulator location is always ready, the permission flow is short and the accuracy is perfect. On the device, location must first find the satellites, its accuracy drops indoors and the user may deny permission. A screen that passes without trouble in the simulator may never have seen these three situations.

The sentences in this section are not things the model measures; they are a rough map of the difference between environments. The measurement is made below in this lesson, with sets of capability names.

## When a Required Capability Is Absent from the Simulator

If an app uses the camera, it declares this in the project settings and asks the user for permission on first use. Because the simulator runs on the computer, it does not present the computer's camera as the device's camera; a camera call either fails in the simulator or returns empty. For location the situation is different: the simulator can give the app a location chosen by the developer as if it were the device's location.

The code that asks for location permission depends on the platform's location framework, so it stands only as source.

```swift
// location permission — SOURCE
import CoreLocation

let manager = CLLocationManager()
manager.requestWhenInUseAuthorization()
```

The first measurement is the meeting of the capabilities an app requires with the capabilities the simulator offers. The app wants the camera and the motion sensor; the simulator offers location, network and keychain. The two sets are disjoint.

```swift
// main.swift — a capability the app requires is absent from the simulator
let required: Set<String> = ["camera", "motion"]
let simulator: Set<String> = ["location", "network", "keychain"]

let missing = Meeting(
    "required-vs-simulator",
    first: required,
    second: simulator,
    result: required.intersection(simulator)
)
missing.report()
```

```
required-vs-simulator: first camera,motion | second keychain,location,network | result empty -> rejection
```

There is no common capability and the resolution is **rejection**: the app cannot find the capabilities it requires in this simulator. In practice this corresponds to a flow that cannot be tested in the simulator once the camera screen is reached. The remedy is not to change the code but to test that flow on a real device.

**DE13.** The measurement was made for two disjoint capability sets. The mixed case, where only some of the required capabilities exist in the simulator, was not measured separately in this table.

## Capabilities the Simulator and the Device Share

If the same app is to run both in the simulator and on the device, it is safe to rely on the capabilities the two share. The simulator offers location, network and keychain; the device offers camera, location, network and motion sensor. The meeting of the two gives the capabilities that behave the same in both environments.

```swift
// main.swift — the capabilities the simulator and the device share
let simulatorSet: Set<String> = ["location", "network", "keychain"]
let deviceSet: Set<String> = ["camera", "location", "network", "motion"]

let shared = Meeting(
    "simulator-vs-device",
    first: simulatorSet,
    second: deviceSet,
    result: simulatorSet.intersection(deviceSet)
)
shared.report()
```

```
simulator-vs-device: first keychain,location,network | second camera,location,motion,network | result location,network -> intersection
```

The resolution is **intersection**: location and network exist in both environments. The keychain appeared only in the simulator set, because in this model it was not written into the device set. This is not a claim about reality but the input of the measurement: we count what is written into the sets, not the platform's real hardware.

**DE14.** The capability sets are the input of the model; they are not claimed to reflect the platform's real capability list. The set of a third environment, for example a different piece of hardware, was not measured.

## The Simulated Location

In the simulator, location does not come from a real satellite reading; the developer chooses a location or plays back a route. When the app has two pieces of location information, the simulated location replaces the real location. This replacement is a **precedence** relation: one wins, the other becomes invisible.

```swift
// main.swift — the simulated location replaces the real location
let realFix = ["real-fix"]
let simulatedFix = ["simulated-fix"]

let fixMeeting = Meeting(
    "location-source",
    first: Set(realFix),
    second: Set(simulatedFix),
    result: Set(simulatedFix)
)
fixMeeting.report()
```

```
location-source: first real-fix | second simulated-fix | result simulated-fix -> precedence
```

The resolution is **precedence**: the result is the same as the second definition. When the app reads location in the simulator, it sees the chosen location, not a location in the field. For this reason location-dependent faults can stay hidden if they are tested only in the simulator: since no real location arrives, situations such as accuracy, latency and permission changes never occur.

**DE15.** The measurement covers a single pair of location sources. How the real location arrives when there is no simulated location, and how far apart the two sources can drift at the same time, were not measured.

These differences produce a list of things that must be tried on the device. Hardware-bound flows such as the camera and microphone, network behavior on an intermittent or slow connection, memory use and heating during long runs, the state of an app that is put in the background and returned to, and the smoothness of touch and scrolling felt with a real finger head this list. None of these can be tested safely in the simulator, because the simulator either does not offer the capability or runs it flawlessly with the computer's power. The practical rule is plain: the simulator is for fast feedback, and the device is the last exam before release.

## Installing on a Device

To install an app in the simulator one need not prove anything to anyone; to install on a device one does. The platform verifies by signature who produced every app that will run on a device and what it is permitted to do. The preparation consists of four parts.

- **Developer identity (certificate):** The digital identity of the person or team that signs the app. It consists of a certificate and a private key tied to it; without the private key a signature cannot be made, so the key may need to be moved to another computer.
- **App identifier:** The package name that identifies the app uniquely in the world, often written in reverse domain name form. Two apps cannot carry the same identifier.
- **Registered device:** An app signed for development opens only on devices registered in advance. The device's unique identifier is added to the team's device list.
- **Entitlements:** The right of the app to use special capabilities such as notifications, keychain sharing or background execution. Even if a capability is used in code, it does not work on the device if the entitlement is not in the profile.

A **provisioning profile** ties these four parts together in a single file: which app identifier, when signed with which certificate, can run on which devices, with which entitlements. The target's settings point to this profile. The signing settings are also defined at project and target level; the value in the target takes precedence over the one in the project.

Two more steps may be needed on the device. The first is making the device ready for development: in the relevant versions of the platform the device asks for a developer mode to be turned on. The second is the device owner trusting, in the settings, the developer of a development-signed app installed on the device for the first time. Both are done once, but when skipped the app installs and still does not open; this is one of the situations that surprises beginners most.

The result of this preparation is also a meeting, but this lesson's model does not measure it: whether the certificate, the profile and the device list fit one another belongs to the platform's signature check. The only thing measured in this lesson is the capability names of the app and the environment once the preparation is complete.

## The Bounding Measurement

The model counts whether a capability exists; it cannot count how well that capability works. Code that runs in the simulator may not run on the device: memory, processor and sensor noise differ in the two environments. To see this, let the simulator and the device offer the same set of capabilities; let one be fast and the other slow. The model compares the sets and sees that the two sets are the same.

```swift
// main.swift — the same capability sets: a performance difference is invisible to the model
let capabilities: Set<String> = ["location", "network"]

let sameCapabilities = Meeting(
    "same-capabilities",
    first: capabilities,
    second: capabilities,
    result: capabilities
)
sameCapabilities.report()
```

```
same-capabilities: first location,network | second location,network | result location,network -> out-of-scope
```

When the two definitions are the same, the classifier sees no meeting: the result is **out-of-scope**. This does not mean the two environments behave the same; it says only that the capability names are the same. Differences of performance, duration and accuracy are outside this model.

The practical rule is this: a test that passes in the simulator shows that the capability exists; it does not show that the capability runs fast and accurately enough on real hardware. Flows with time and memory concerns should be tested on at least one real device before release. In the same way, flows that depend on sensor data can be tested in the simulator only with chosen values; the noise or interruption of a real sensor does not occur there.

**DE16.** The measurement counted the existence of a capability. The same capability running at a different speed or with a different accuracy in the two environments, and the memory and processor difference, were not measured.

## Summary

- If a capability the app requires is absent from the simulator, the meeting is rejected; the flow is tested on a real device.
- The capabilities the simulator and the device share are the intersection of the sets.
- The simulated location replaces the real location; the resolution is precedence.
- The model counts the existence of a capability; a performance difference stays outside the measurement.
- This lesson's resolution: **rejection**. If a required capability is not in the environment, the app cannot find it in that environment.

## Next Step

This lesson measured where the app will run and what will be missing. When something goes wrong while it runs, the problem has to be found. The next lesson covers the basics of debugging: the union of the breakpoints of two sources, the intersection of filters, and the precedence of the scheme setting over the code's default.
