This document covers BitChat's iOS share extension (ShareViewController) and custom URL scheme handling (bitchat://), which enable users to share content from other apps into BitChat. The share extension uses iOS App Groups for inter-process communication, allowing shared text and URLs to be passed from the extension to the main app and immediately broadcast to the active channel.
For information about how shared content is actually sent to peers after being received by the main app, see 3.4 Message Routing and Transport Selection For application lifecycle coordination, see 2.2 Application Lifecycle Management
The share extension operates as a separate process with limited lifetime and capabilities. It communicates with the main BitChat app via shared UserDefaults in an App Group container. The App Group ID is retrieved from the AppGroupID key in the Info.plist bitchatShareExtension/ShareViewController.swift16 and defined in the main app as BitchatApp.groupID bitchat/BitchatApp.swift15 Both targets must include the com.apple.security.application-groups entitlement.
The following diagram illustrates the lifecycle of a share action from the user's perspective through the code entities involved in cross-process communication.
Title: BitChat Share Extension Data Flow
Sources: bitchatShareExtension/ShareViewController.swift14-179 bitchat/BitchatApp.swift13-68
The share extension is implemented as a modern UIKit view controller in bitchatShareExtension/ShareViewController.swift bitchatShareExtension/ShareViewController.swift14 It avoids the deprecated SLComposeServiceViewController from the Social framework to provide a custom UI.
| Component | Type | Purpose |
|---|---|---|
ShareViewController | UIViewController | Main extension entry point bitchatShareExtension/ShareViewController.swift14 |
statusLabel | UILabel | Displays processing status and confirmation messages bitchatShareExtension/ShareViewController.swift27-35 |
groupID | String | App Group identifier retrieved from AppGroupID key in Info.plist bitchatShareExtension/ShareViewController.swift16 |
processShare() | Method | Extracts content from extensionContext.inputItems bitchatShareExtension/ShareViewController.swift53-98 |
loadFirstURL(from:completion:) | Method | Asynchronously loads URL from attachment providers bitchatShareExtension/ShareViewController.swift108-131 |
loadFirstPlainText(from:completion:) | Method | Asynchronously loads plain text from providers bitchatShareExtension/ShareViewController.swift133-150 |
saveToSharedDefaults(content:type:) | Method | Writes to App Group UserDefaults bitchatShareExtension/ShareViewController.swift164-169 |
Sources: bitchatShareExtension/ShareViewController.swift14-179
The extension prioritizes URLs over plain text because Safari and many apps pass URLs through attributedContentText bitchatShareExtension/ShareViewController.swift61-64 The detection uses NSDataDetector for URL pattern matching bitchatShareExtension/ShareViewController.swift100-106 and attempts multiple UTType identifiers (UTType.url.identifier, "public.url", "public.file-url") to maximize compatibility bitchatShareExtension/ShareViewController.swift109
Title: Content Parsing and Validation Logic
Sources: bitchatShareExtension/ShareViewController.swift53-98
The extension and main app communicate through three synchronized keys in the App Group container. The App Group ID is retrieved from the Info.plist bitchatShareExtension/ShareViewController.swift16 bitchatShareExtension/Info.plist5-6
| Key | Type | Description | Set By | Read By |
|---|---|---|---|---|
"sharedContent" | String | URL as JSON or plain text content | Extension | Main app |
"sharedContentType" | String | "url" or "text" discriminator | Extension | Main app |
"sharedContentDate" | Date | Timestamp when content was shared | Extension | Main app |
Sources: bitchatShareExtension/ShareViewController.swift164-169 bitchat/BitchatApp.swift15 bitchatShareExtension/Info.plist5-6
When the extension shares a URL, it encodes both the URL and optional title as JSON bitchatShareExtension/ShareViewController.swift153-157:
Sources: bitchatShareExtension/ShareViewController.swift153-163
BitChat registers the custom URL scheme bitchat in its Info.plist bitchat/Info.plist23-31 This scheme allows the share extension or external apps to trigger BitChat.
The main app handles incoming URLs via the onOpenURL modifier in BitchatApp.swift bitchat/BitchatApp.swift48-50 This calls runtime.handleOpenURL(url), where runtime is the AppRuntime instance bitchat/BitchatApp.swift49
Additionally, the NotificationService handles deep linking through notification responses. When a user interacts with a notification, NotificationDelegate.shared calls runtime.handleNotificationResponse bitchat/BitchatApp.swift114-118
Title: Application URL Handling
Sources: bitchat/BitchatApp.swift48-61 bitchat/Info.plist23-31 bitchat/Services/NotificationService.swift105-121
The share extension has a constrained lifecycle managed by iOS:
ShareViewController.viewDidLoad() is called, setting up the UI with statusLabel bitchatShareExtension/ShareViewController.swift37-46NSItemProvider using DispatchQueue.global() coordination bitchatShareExtension/ShareViewController.swift47-49statusLabel shows confirmation message using localized strings bitchatShareExtension/ShareViewController.swift18-25extensionContext.completeRequest() bitchatShareExtension/ShareViewController.swift172-178Sources: bitchatShareExtension/ShareViewController.swift37-50 bitchatShareExtension/ShareViewController.swift172-178
The main app's AppRuntime is responsible for validating the freshness of shared content recorded in the App Group defaults. The extension records the timestamp via sharedContentDate bitchatShareExtension/ShareViewController.swift168 This prevents stale content from being sent if the app is opened long after the share action occurred.
Sources: bitchatShareExtension/ShareViewController.swift168 bitchat/BitchatApp.swift48-61
The ShareViewController handles several edge cases during the extraction process:
| Failure Case | Behavior |
|---|---|
| No items in context | Finishes with Strings.nothingToShare bitchatShareExtension/ShareViewController.swift56 |
| No attachments but has title | Saves attributedTitle as text bitchatShareExtension/ShareViewController.swift70-72 |
| Provider load fails | Attempts fallback to plain text bitchatShareExtension/ShareViewController.swift84-95 |
| JSON encoding fails | Finishes with Strings.failedToEncode bitchatShareExtension/ShareViewController.swift162 |
Sources: bitchatShareExtension/ShareViewController.swift53-98 bitchatShareExtension/ShareViewController.swift153-163
Refresh this wiki
This wiki was recently refreshed. Please wait 6 days to refresh again.