# Share for iOS A native SwiftUI client for the `share` swarm. It uses the same Go engine as the CLI, compiled for iOS with gomobile, so the phone is a real peer: it can seed files, receive files, verify chunks, and fall back to the relay pipe when a direct connection is blocked. ``` apps/ios/ project.yml XcodeGen project (source of truth) Share/ SwiftUI sources, assets, Info.plist GoBridge/ nested Go module exposing swarm to Swift build-go.sh builds Share.xcframework with gomobile build.sh simulator or signed device build run-device.sh install + launch on a paired iPhone Branding/make-icon.swift regenerates the app icon ``` ## Build Requirements: Xcode, `xcodegen`, Go 1.26+ for the gomobile bridge, and network access the first time `gomobile` is installed. (The CLI itself still builds with the repo's Go 1.25 requirement.) ```sh cd apps/ios # Simulator (Apple Silicon) ./build.sh simulator # Signed device build (team RX6767S6BW) ./build.sh device # Install on the paired iPhone over Wi-Fi ./run-device.sh FeelsCringeMan ``` `build.sh` regenerates `Share.xcframework` before running `xcodegen generate`; the XCFramework and the generated `.xcodeproj` are build artifacts and are ignored by git. ## Smoke tests The app has two launch-argument driven tests that write `Documents/share-selftest.txt`; console output is unreliable on a simulator and unavailable on a device. Receive (the app is the peer that downloads): ```sh # 1. Start a relay on the Mac (all interfaces, so a phone can reach it). go run . relay --host 0.0.0.0 --port 9009 # 2. Launch the test. Use 127.0.0.1 for the simulator, or the Mac's LAN # address for a physical phone. xcrun simctl launch dev.tzgyn.share \ -shareSelfTest -shareSelfTestRelay 127.0.0.1:9009 \ -shareSelfTestCode 1234-selftest-share-apple # 3. Seed a file from the CLI. go run . send --relay 127.0.0.1:9009 --code 1234-selftest-share-apple /tmp/test.bin # 4. Read the report from the simulator container. DATA=$(xcrun simctl get_app_container dev.tzgyn.share data) cat "$DATA/Documents/share-selftest.txt" ``` Send (the app seeds a generated 2 MiB file): ```sh xcrun simctl launch dev.tzgyn.share \ -shareSelfTestSend -shareSelfTestRelay 127.0.0.1:9009 \ -shareSelfTestCode 1234-selftest-send-apple go run . --relay 127.0.0.1:9009 --out /tmp/received --one-time \ 1234-selftest-send-apple ``` On a physical phone, read the report with: ```sh xcrun devicectl device copy from --device \ --domain-type appDataContainer --domain-identifier dev.tzgyn.share \ --source Documents/share-selftest.txt --destination /tmp/share-selftest.txt ``` ## How it works - `GoBridge/share.go` keeps one `swarm.Client` per room and exposes `Start`, `StatusJSON`, and `Stop`. Progress crosses the gomobile boundary as JSON so Swift only decodes plain value types. - The app copies picked files into `Documents/Seeds/` before starting a room: the document picker's security-scoped URL is only valid while the picker callback is on the stack, not for the lifetime of a transfer. - Received files are written to `Documents/Received/`. `UIFileSharingEnabled` makes that folder visible in Files → On My iPhone → Share. - The default relay is the project's own `share.tzgyn.dev:9009`; the CLI and the iOS app both use it. For local transfers, run `share relay` on a Mac and enter its LAN address (`192.168.x.x:9009`) under Relay in the app. ## Notes - The app runs one room at a time; starting another requires stopping the current one. - Receiving uses `oneTime: true`, so the room stops after every file known at that moment is complete. Sending keeps seeding until Stop. - iOS can suspend the app when it leaves the foreground; if the relay connection dies, the room card shows the error and a new room can be started.