Main application entry point implementing SwiftUI App protocol.
@main
struct IPA_InstallApp: AppDescription: Main application structure using document-based architecture.
Properties:
body: some Scene- Application scene configuration
Scene Configuration:
- DocumentGroup: Handles .ipa file associations and viewing
- Settings: Provides access to ECID configuration
Usage:
DocumentGroup(viewing: IPADocument.self) { fileConfig in
ShellOutputView(url: fileConfig.fileURL)
}Document model for handling iOS Package Archive files.
extension UTType {
static var ipa: UTType {
UTType(importedAs: "com.apple.itunes.ipa")
}
}Description: Extends UTType to support .ipa file recognition.
enum IPADocumentError: LocalizedErrorCases:
.notImplementedError(String)- For unsupported operations.invalidFileFormat- When file format is invalid.fileAccessError- When file cannot be accessed
Properties:
errorDescription: String?- Localized error descriptions
struct IPADocument: FileDocumentDescription: Document model conforming to FileDocument protocol for .ipa files.
Properties:
text: String- Document content placeholderstatic var readableContentTypes: [UTType]- Supported file types
Initializers:
init(text: String = "")
init(configuration: ReadConfiguration) throwsMethods:
func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapperUsage Notes:
- Read-only implementation (writing throws
notImplementedError) - Validates file accessibility without reading contents
- Designed for path-based operations with cfgutil
Core business logic for IPA installation process management.
enum ProcessError: LocalizedErrorCases:
.invalidECID(String)- ECID format validation failure.cfgutilNotFound- cfgutil tool not available.invalidIPAFile- IPA file validation failure.deviceNotFound- Target device not connected.installationFailed(String)- Installation process failure
Properties:
errorDescription: String?- Detailed error descriptions with guidance
@Observable
class ProcessModelDescription: Observable model managing the IPA installation process.
Properties:
var output: String = "" // Real-time process output
var isProcessing: Bool = false // Processing state flag
var lastError: ProcessError? // Last encountered errorPrivate Properties:
private let cfgutilPaths = [ // Common cfgutil installation paths
"/usr/local/bin/cfgutil",
"/usr/bin/cfgutil",
"/opt/homebrew/bin/cfgutil"
]Public Methods:
Description: Main processing method for IPA installation.
Parameters:
url: URL- Path to the .ipa fileecid: String- Target device ECID
Process Flow:
- Input validation (ECID format, file existence)
- cfgutil tool detection
- Device connectivity verification
- IPA installation execution
- Real-time output streaming
Error Handling: Catches and handles all ProcessError types.
Private Methods:
Description: Validates input parameters before processing.
Validation Checks:
- ECID format using regex pattern
- File existence verification
- .ipa extension validation
Description: Validates ECID format using regular expressions.
Pattern: ^0x[0-9A-Fa-f]{13,16}$
- Must start with "0x"
- Followed by 13-16 hexadecimal digits
- Case-insensitive hex validation
Description: Locates cfgutil executable in common installation paths.
Search Paths:
/usr/local/bin/cfgutil(manual installation)/usr/bin/cfgutil(system installation)/opt/homebrew/bin/cfgutil(Homebrew installation)
Returns: Full path to cfgutil executable
Throws: ProcessError.cfgutilNotFound if not found
Description: Verifies target device is connected and accessible.
Process Execution:
cfgutil --ecid [ECID] listError Handling: Throws ProcessError.deviceNotFound on failure
Description: Executes the IPA installation process.
Command Execution:
cfgutil --ecid [ECID] install-app [IPA_PATH]Features:
- Real-time stdout/stderr streaming
- Asynchronous execution using Coquille
- Progress updates via output streaming
Description: Thread-safe output updating on main actor.
Usage: Called from process output streams to update UI.
Description: Centralized error handling with logging and UI updates.
Actions:
- Updates
lastErrorproperty - Appends error to output stream
- Logs error using OSLog
SwiftUI view for device ECID configuration.
struct SettingsView: ViewDescription: Settings interface for device configuration.
Properties:
@AppStorage("Phone_ECID") private var ecid = "0x1234567890ABCD" // Persistent ECID storage
@State private var isValidECID = true // Validation state
@State private var showingHelp = false // Help popover stateLayout Structure:
- Device Configuration Section: ECID input with validation
- About ECID Section: Information and guidance
- Help Popover: Detailed ECID location instructions
Methods:
Description: Real-time ECID validation with visual feedback.
Validation Logic:
- Trims whitespace
- Applies regex pattern:
^0x[0-9A-Fa-f]{13,16}$ - Updates validation state for UI feedback
Visual Feedback:
- Green checkmark for valid ECID
- Orange warning for invalid format
- Descriptive error messages
Description: Comprehensive help content for ECID discovery.
Content Sections:
- iOS Settings method
- Apple Configurator 2 method
- Xcode method
- Format examples
UI Configuration:
- Fixed frame size: 450x300
- Form-based layout
- Navigation title integration
Main interface view combining output display and status monitoring.
struct ShellOutputView: ViewDescription: Primary user interface for IPA installation process.
Properties:
@State var model = ProcessModel() // Process management model
@AppStorage("Phone_ECID") private var ecid = "" // Device ECID from settings
var url: URL? // IPA file URLLayout Components:
Description: Top status bar showing processing state and configuration.
Status Indicators:
- Processing: Progress indicator with "Installing..." text
- Error: Warning icon with "Installation Failed" text
- Complete: Checkmark with "Ready" text
- ECID Display: Shows current ECID or "Not Set"
Styling:
- Control background color
- Separator border
- Horizontal padding and vertical spacing
Description: Prominent error display banner.
Features:
- Orange warning icon
- Error title and description
- Orange-themed background and border
- Rounded corner styling
Layout:
- Horizontal stack with icon, text, and spacer
- Vertical text stack for title and description
- Background with opacity and stroke overlay
Main View Structure:
VStack(spacing: 0) {
statusBar
ScrollViewReader { proxy in
ScrollView {
// Error banner (conditional)
// Output text display
}
}
}Features:
- Auto-scroll: Automatic scrolling to latest output
- Text Selection: Enabled for output copying
- Monospaced Font: Terminal-like appearance
- Real-time Updates: Reactive to model changes
Lifecycle Methods:
Description: Handles view initialization and automatic processing.
Logic:
- Checks for valid URL and ECID configuration
- Automatically starts installation process
- Shows configuration warning if ECID not set
Auto-start Conditions:
if let url, !ecid.isEmpty {
Task { await model.process(url: url, ecid: ecid) }
}static var ipa: UTType {
UTType(importedAs: "com.apple.itunes.ipa")
}Purpose: Enables macOS file association and "Open with" functionality.
@AppStorage("Phone_ECID") private var ecid: StringPurpose: Persistent storage for device ECID across app launches.
@Observable
class ProcessModelPurpose: Reactive UI updates using Swift's observation framework.
All error enums conform to LocalizedError for user-friendly messages:
var errorDescription: String? {
switch self {
case .invalidECID(let ecid):
return "Invalid ECID format: \(ecid). Expected format: 0x[16 hex digits]"
// Additional cases...
}
}do {
try await runInstallation(...)
} catch let error as ProcessError {
await handleError(error)
} catch {
await handleError(.installationFailed(error.localizedDescription))
}- Non-blocking error banners
- Status indicators
- Contextual error messages
- Recovery suggestions
let process = Process(
command: .init(cfgutilPath, arguments: ["--ecid", ecid, "install-app", path]),
stdout: { stdout in
Task { await self.updateOutput(stdout) }
},
stderr: { stderr in
Task { await self.updateOutput(stderr) }
}
)@Observablefor reactive data flow@AppStoragefor persistence@Statefor view-local state managementTaskfor async operations
- Document-based app architecture
- UTType declarations for file associations
- Secure file access through user selection