forked from jsnbuchanan/crowd-funder-for-time-pwa
Implement iOS Share Extension to enable native image sharing from Photos and other apps directly into TimeSafari. Users can now share images from the iOS share sheet, which will open in SharedPhotoView for use as gifts or profile pictures. iOS Native Implementation: - Add TimeSafariShareExtension target with ShareViewController - Configure App Groups for data sharing between extension and main app - Implement ShareViewController to process shared images and convert to base64 - Store shared image data in App Group UserDefaults - Add ShareImageBridge utility to read shared data from App Group - Update AppDelegate to handle shared-photo deep link and bridge data to JS JavaScript Integration: - Add checkAndStoreNativeSharedImage() in main.capacitor.ts to read shared images from native layer via temporary file bridge - Convert base64 data to data URL format for compatibility with base64ToBlob - Integrate with existing SharedPhotoView component - Add "shared-photo" to deep link validation schema Build System: - Integrate Xcode 26 / CocoaPods compatibility workaround into build-ios.sh - Add run_pod_install_with_workaround() for explicit pod install - Add run_cap_sync_with_workaround() for Capacitor sync (which runs pod install internally) - Automatically detect project format version 70 and apply workaround - Remove standalone pod-install-workaround.sh script Code Cleanup: - Remove verbose debug logs from ShareViewController, AppDelegate, and main.capacitor.ts - Retain essential logger calls for production debugging Documentation: - Add ios-share-extension-setup.md with manual Xcode setup instructions - Add ios-share-extension-git-commit-guide.md for version control best practices - Add ios-share-implementation-status.md tracking implementation progress - Add native-share-target-implementation.md with overall architecture - Add xcode-26-cocoapods-workaround.md documenting the compatibility issue The implementation uses a temporary file bridge (AppDelegate writes to Documents directory, JS reads via Capacitor Filesystem plugin) as a workaround for Capacitor plugin auto-discovery issues. This can be improved in the future by properly registering ShareImagePlugin in Capacitor's plugin registry.
4.8 KiB
4.8 KiB
iOS Share Extension Setup Instructions
Date: 2025-01-27
Purpose: Step-by-step instructions for setting up the iOS Share Extension in Xcode
Prerequisites
- Xcode installed
- iOS project already set up with Capacitor
- Access to Apple Developer account (for App Groups)
Step 1: Create Share Extension Target
- Open
ios/App/App.xcodeprojin Xcode - In the Project Navigator, select the App project (top-level item)
- Click the + button at the bottom of the Targets list
- Select iOS → Share Extension
- Click Next
- Configure:
- Product Name:
TimeSafariShareExtension - Bundle Identifier:
app.timesafari.shareextension(must match main app's bundle ID with.shareextensionsuffix) - Language: Swift
- Product Name:
- Click Finish
Step 2: Configure Share Extension Files
The following files have been created in ios/App/TimeSafariShareExtension/:
ShareViewController.swift- Main extension logicInfo.plist- Extension configuration
Verify these files exist and are added to the Share Extension target.
Step 3: Configure App Groups
App Groups allow the Share Extension and main app to share data.
For Main App Target:
- Select the App target in Xcode
- Go to Signing & Capabilities tab
- Click + Capability
- Select App Groups
- Click + to add a new group
- Enter:
group.app.timesafari - Ensure it's checked/enabled
For Share Extension Target:
- Select the TimeSafariShareExtension target
- Go to Signing & Capabilities tab
- Click + Capability
- Select App Groups
- Click + to add a new group
- Enter:
group.app.timesafari(same as main app) - Ensure it's checked/enabled
Important: Both targets must use the exact same App Group identifier.
Step 4: Configure Share Extension Info.plist
The Info.plist file should already be configured, but verify:
- Select
TimeSafariShareExtension/Info.plistin Xcode - Ensure it contains:
NSExtensionPointIdentifier=com.apple.share-servicesNSExtensionPrincipalClass=$(PRODUCT_MODULE_NAME).ShareViewControllerNSExtensionActivationSupportsImageWithMaxCount=1
Step 5: Add ShareImageBridge to Main App
- The file
ios/App/App/ShareImageBridge.swifthas been created - Ensure it's added to the App target (not the Share Extension target)
- In Xcode, select the file and check the Target Membership in the File Inspector
Step 6: Build and Test
- Select the App scheme (not the Share Extension scheme)
- Build and run on a device or simulator
- Open Photos app
- Select an image
- Tap Share button
- Look for TimeSafari Share in the share sheet
- Select it
- The app should open and navigate to the shared photo view
Step 7: Troubleshooting
Share Extension doesn't appear in share sheet
- Verify the Share Extension target builds successfully
- Check that
Info.plistis correctly configured - Ensure the extension's bundle identifier follows the pattern:
{main-app-bundle-id}.shareextension - Clean build folder (Product → Clean Build Folder)
App Group access fails
- Verify both targets have the same App Group identifier
- Check that App Groups capability is enabled for both targets
- Ensure you're signed in with a valid Apple Developer account
- For development, you may need to enable App Groups in your Apple Developer account
Shared image not appearing
- Check Xcode console for errors
- Verify
ShareViewController.swiftis correctly implemented - Ensure the deep link
timesafari://shared-photois being handled - Check that the native bridge method is being called
Build errors
- Ensure Swift version matches between targets
- Check that all required frameworks are linked
- Verify deployment targets match between main app and extension
Step 8: Native Bridge Implementation (TODO)
Currently, the JavaScript code needs a way to call the native getSharedImageData() method. This requires one of:
- Option A: Create a minimal Capacitor plugin
- Option B: Use Capacitor's existing bridge mechanisms
- Option C: Expose the method via a custom URL scheme parameter
The current implementation in main.capacitor.ts has a placeholder that needs to be completed.
Next Steps
After the Share Extension is set up and working:
- Complete the native bridge implementation to read from App Group
- Test end-to-end flow: Share image → Extension stores → App reads → Displays
- Implement Android version
- Add error handling and edge cases