From Visible Device to Trusted Device
For iloader, device selection is not a dropdown problem; it is the process of turning a transport-level sighting into a device that the rest of the workflow can safely use. This chapter follows that process from usbmuxd enumeration through lockdown metadata, user trust, pairing generation, and committed native state. The practical result is a way to tell whether a failure means “the computer cannot see the phone,” “the phone cannot answer,” or “the user has not yet authorized the connection.”
Enumeration is only the first answer
The host service called usbmuxd is the first boundary in iloader's device path. The application connects to it and asks for the devices it knows about. That answer is a transport inventory, not yet a promise that every device is ready for an installation. A device record includes an identifier, a UDID, a connection type, and enough information for iloader to try the next connection. The code recognizes USB, Network, and Unknown connections, so visibility is not limited to one physical transport.
For each returned device, iloader creates a provider and attempts a lockdown connection. Lockdown is the device-facing service used here to read DeviceName and ProductVersion. Those values serve two different purposes. The name gives the interface a human-readable label, while the product version gives later pairing logic a compatibility input. The connection type tells the user how the host reached the device, but it does not itself establish that the device has trusted the computer.
This per-device work is deliberately represented as a collection of individual results. iloader waits for the metadata requests together, then returns either a device description or an error for each entry. If one connected device cannot answer a lockdown request, the application can report that problem while retaining other devices that were successfully described. That is more useful than treating the entire inventory as all-or-nothing: one damaged cable, locked phone, or unavailable connection does not have to hide every other candidate.
The result type also keeps a useful distinction between “no candidates exist” and “a candidate exists but could not be described.” An empty list leads the interface to say that no devices were found. A failed per-device result can produce an error toast while successfully described devices remain selectable. Those are different next actions: the first points toward host service or physical connection setup, while the second points toward the particular device's lockdown or trust state. iloader does not solve either problem automatically, but it preserves enough structure for the user to choose a less random remedy.
There is also a time gap between discovery and selection. A device can be unplugged, locked, or moved to another connection after its metadata has been read. That is why selection reconnects to usbmuxd instead of treating the original provider as permanent. The second connection is not redundant ceremony; it tests whether the candidate is still reachable at the moment iloader is about to make it active and generate pairing material. If it fails, the application can leave the previously committed device state intact rather than replacing it with an object that was valid only during the refresh.
The product version has a similar role as a guardrail. It is collected during discovery, carried with the device description, and then consulted by the pairing path to choose the material appropriate to the device generation. A version string on a card is therefore more than display text, even though the interface does not show the branch it will trigger. The source has an explicit compatibility split for the newer remote-pairing material; keeping the version attached to the device lets selection and later pairing make that decision without asking the user to understand the protocol first.
The distinctions matter in ordinary use. If usbmuxd cannot be reached, iloader has no inventory to display. If usbmuxd returns a device but the lockdown connection fails, the host has learned that something is present but not enough to identify it. If lockdown answers but a value is missing or is not the expected string, metadata construction still fails. The interface presents these as device-loading errors and offers connection or Trust-related guidance. None of these outcomes should be summarized as a generic “the installer is broken,” because each one points to a different boundary.
The application also prevents a stale list from masquerading as current state. A refresh starts a new listing request only when another listing is not already in progress. After the new results arrive, a previously selected device is checked against the refreshed list. If it is no longer available, iloader clears the selection. A card that was active a moment ago therefore cannot remain the native target merely because the screen has not yet been redrawn.
There is a small but important asymmetry in automatic selection. After listing devices, the interface asks the native side whether each device has stored RPPairing material and selects the first device for which the check succeeds. On the newer pairing path, this can make a familiar device active without asking the user to repeat the full pairing flow. On the older path, the helper reports eligibility without requiring an RPPairing cache because that material is not needed there. Automatic selection is consequently a convenience rule, not a general statement that every connected device is equally trusted or that a cached artifact replaces a live connection.
The UI's labels also represent different identities. The display name is for a person; the numeric device ID is used by the interface when it compares the active card with a refreshed result; the UDID is carried into pairing work and forms the key for the stored RPPairing data. The source keeps these values together, but it does not give them one interchangeable meaning. A name can identify a device to a user without being a safe cache key, while a cache key can distinguish a device without being helpful on a screen. Keeping those roles separate is essential when reconnects, multiple devices, or stale results enter the picture.
Selection is a trust-and-pairing transaction
Clicking a device begins a second phase. The frontend assigns the selection a request number, clears any old pairing modal, marks the device as waiting, and asks the native side to set it as selected. The native command first handles the special case of clearing selection. For a real device, it reconnects to usbmuxd, creates a fresh cancellation token, cancels an older pairing request if one exists, and starts generating the pairing artifact. Only after that work succeeds does it store the device description together with the pairing bytes.
That ordering is the core safety property. The screen can show a device card immediately, but the native state is not committed until the device can participate in the pairing path. If pairing fails, the pending UI is cleared and the earlier committed selection is not replaced by a half-prepared object. Later installation code can therefore assume that a selected native device has both the metadata needed to communicate and the pairing material needed by operations that use it. The assumption is conditional on the device remaining available; it is not a lifetime guarantee.
Pairing often requires an action from the person holding the device. iloader's English guidance tells the user to unlock the device, accept the Trust prompt, and enter the passcode if requested. That interaction explains why “visible” and “trusted” are separate states. A computer can discover a device through its host service while the device still refuses the session needed to read or write the information iloader needs. The repository does not define Apple's trust protocol; it coordinates the connection and gives the user a place to respond when the device asks for authorization.
The pairing operation itself has a cancellation boundary. The native code passes a cancellation token into the pairing function, which checks it while waiting for lockdown material and while generating the newer remote-pairing material. The user can close the pairing modal or press its Cancel button, both of which ask the native side to cancel. Starting another selection also cancels the previous token. This matters when a user notices that the wrong phone was selected or when a trust prompt will not appear, because the application can stop waiting rather than leave an unbounded background attempt.
Cancellation is not rollback. It can stop the in-flight work that observes the token, but it does not promise to erase a pairing record that an external service has already created or undo a file that has already been transferred. The source uses cancellation to control the current pairing task, not to wrap the entire device relationship in a transaction. That is a realistic boundary for a workflow that crosses the host, the phone, and library-managed protocol sessions.
The frontend request number solves a different race. Suppose a user starts selecting one phone, then quickly selects another. The first native call may finish after the second selection has begun. When a result arrives, the interface checks whether its request number is still current. If it is not, the result is ignored. This prevents an older success from making the first phone appear active again, or an older error from replacing the explanation for the current choice. The request number protects the meaning of the screen; the native cancellation token limits the work behind the screen. Neither mechanism substitutes for the other.
The sequence is easier to see when the actors are kept separate:
The diagram compresses several library calls into “generate pairing material”; it does not claim that pairing is a single request. The important chronology is that enumeration precedes selection, selection triggers pairing, and commitment follows successful pairing. A canceled or failed branch does not become the active device. The UI may also disregard a late result if another request has superseded it.
What the device state enables—and what it cannot promise
Once selection succeeds, the native state contains a device description and its pairing bytes. That lets later commands avoid repeating the entire pairing process for every action. The pairing bytes can be combined with a cached newer-device artifact or regenerated when the stored representation is invalid; the exact version-dependent construction is a separate concern from the selection gate. Settings can also delete stored RPPairing material and force the user to select and pair again. Persistence shortens the normal path, while deletion provides a controlled way to recover from stale or corrupted pairing state.
The cache still does not make the device autonomous. iloader must reconnect to usbmuxd and obtain a provider for operations such as placing a file. The phone must still be present, reachable, and willing to answer. A cached artifact can reduce work and preserve device-specific material, but it cannot repair a missing host service, a changed trust relationship, a locked device, or a device that has disappeared. This is the same distinction as between a remembered account label and a live developer session: persistence can preserve information, not recreate an external capability by itself.
The connection type provides another useful diagnostic clue without becoming a verdict. The source can describe a network connection, but localized pairing guidance suggests reconnecting by USB when pairing fails. That is practical troubleshooting, not a statement that network connections are universally invalid. Similarly, a device that appears as Unknown deserves investigation, but the label alone does not identify the cause. The correct next question remains which boundary failed: discovery, lockdown, trust, pairing, or later transfer.
This way of reading selection changes the user's expectations. A successful refresh means iloader has obtained a current inventory and, for successful entries, enough lockdown metadata to describe candidates. A successful selection means more: the chosen device completed the pairing work required by the source's current compatibility path, and the resulting state was committed for later commands. A later installation can still fail because account authentication, signing resources, or app transfer have their own boundaries. But the device phase has at least established a meaningful starting condition rather than a card that merely looks active.
The most useful question after this phase is therefore not “why is my phone listed?” It is “what authority has been established for the next operation?” iloader's answer is layered: usbmuxd supplied a candidate, lockdown supplied identity and version, the user supplied trust when required, pairing generation supplied the material later operations need, and native state committed the result only after those steps. The device is now prepared to meet the other major prerequisite—the Apple identity and developer session that give an installation its signing authority.