96 lines
3.4 KiB
Markdown
96 lines
3.4 KiB
Markdown
# Deploying the managed iOS app
|
||||
|
|
|
|||
|
|
VoiceCat's supported iOS client is the .NET 10 UIKit application in
|
|||
|
|
`clients/apple/dotnet/VoiceCat.iOS`. The checked-in scripts build its native Opus/RNNoise
|
|||
|
|
dependency, compile and sign the managed app and Swift ReplayKit extension, stage the bundle,
|
|||
|
|
install it, and launch it on a paired physical device.
|
|||
|
|
|
|||
|
|
## Prerequisites
|
|||
|
|
|
|||
|
|
- macOS 27, Xcode 27, .NET SDK 10.0.401, and the matching iOS workload.
|
|||
|
|
- An unlocked, trusted iPhone connected by USB or visible to Xcode over the network.
|
|||
|
|
- Apple Development profiles for `me.iamtalon.voicecat` and
|
|||
|
|
`me.iamtalon.voicecat.broadcast`, both with App Group `group.me.iamtalon.voicecat`.
|
|||
|
|
|
|||
|
|
List available devices:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
clients/apple/dotnet/deploy-ios-device.sh --list
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Build, install, and launch
|
|||
|
|
|
|||
|
|
Set the Apple developer team explicitly. The .NET host and Xcode-built extension use separate
|
|||
|
|
build systems, and Xcode needs the team to select the extension profile.
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
export VOICECAT_DEVELOPMENT_TEAM=FJV8L966W4
|
|||
|
|
clients/apple/dotnet/build-ios-device.sh --configuration Debug
|
|||
|
|
clients/apple/dotnet/deploy-ios-device.sh \
|
|||
|
|
--device "Talon’s iPhone" \
|
|||
|
|
--configuration Debug \
|
|||
|
|
--no-build
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
The verified bundle is staged at `dist/ios-managed-device/VoiceCat.iOS.app`. Omit `--no-build`
|
|||
|
|
to build and deploy in one command. Add `--console` to attach the launch to device logs.
|
|||
|
|
|
|||
|
|
Confirm that the process stayed alive:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
xcrun devicectl device info processes --device "Talon’s iPhone" | rg VoiceCat
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Signing findings
|
|||
|
|
|
|||
|
|
The development team ID is `FJV8L966W4`. Do not infer it from the parenthesized suffix in an
|
|||
|
|
Apple Development certificate name; that value can identify the certificate holder and need
|
|||
|
|
not equal a profile's `TeamIdentifier`.
|
|||
|
|
|
|||
|
|
The extension wrapper uses automatic signing with installed profiles. If a profile is absent
|
|||
|
|
and Xcode has a valid signed-in developer account, permit Xcode to create or download it:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
export VOICECAT_ALLOW_PROVISIONING_UPDATES=1
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Leave that variable unset when valid profiles are already installed. A stale command-line Xcode
|
|||
|
|
account can otherwise make provisioning updates fail even though offline signing can succeed.
|
|||
|
|
|
|||
|
|
## Troubleshooting
|
|||
|
|
|
|||
|
|
### Stale CMake source path
|
|||
|
|
|
|||
|
|
After moving the native shim from `dotnet/native` to `native/media`, an old CMake cache can
|
|||
|
|
report a source-directory mismatch. Move the generated directories aside and rebuild:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
mv dotnet/artifacts/native-build-ios-arm64-cmake /tmp/
|
|||
|
|
mv dotnet/artifacts/native-build-iossimulator-arm64-cmake /tmp/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Locked restore reports changed runtime identifiers
|
|||
|
|
|
|||
|
|
The managed libraries' lock files must include `ios-arm64` and `iossimulator-arm64`. Regenerate
|
|||
|
|
them after runtime changes, then verify that dependency versions did not change:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
/usr/local/share/dotnet/dotnet restore \
|
|||
|
|
clients/apple/dotnet/VoiceCat.iOS/VoiceCat.iOS.csproj \
|
|||
|
|
-p:VoiceCatIosStatic=true \
|
|||
|
|
--force-evaluate
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Developer disk image cannot be mounted
|
|||
|
|
|
|||
|
|
CoreDevice errors 10003 or 12040 mean the phone locked. Unlock it, keep the display awake, and
|
|||
|
|
rerun deployment with `--no-build`.
|
|||
|
|
|
|||
|
|
## Verified hardware result
|
|||
|
|
|
|||
|
|
On 2026-09-19, the Debug build completed with .NET 10.0.401 and Xcode 27.0. The host and
|
|||
|
|
ReplayKit extension were signed under team `FJV8L966W4`, installed wirelessly on Talon's iPhone,
|
|||
|
|
launched as `me.iamtalon.voicecat`, and remained in the device process list. Audio,
|
|||
|
|
background/lock behavior, Bluetooth, ReplayKit, ScreenCaptureKit, and VoiceOver remain separate
|
|||
|
|
manual hardware gates.
|