feat(ios): register SharedImage via CAPBridgeViewController subclass (Phase 2B-1)

Introduce AppBridgeViewController, a CAPBridgeViewController subclass that
registers the app-local SharedImagePlugin from capacitorDidLoad(), where
the Capacitor bridge is guaranteed to exist. This is the first step toward
replacing AppDelegate's timed retry registration with a deterministic,
bridge-ready registration point.

Point the existing root bridge controller in Main.storyboard at
AppBridgeViewController (same VC id/scene; only the custom class changes)
and add the new file to the App target in project.pbxproj.

The existing AppDelegate registration and its retry loop are intentionally
left in place as a temporary safety net, so the plugin is now registered
from both sites during this phase. No diagnostics, retry logic, JS, or
Android code changed; plugin name ("SharedImage") and implementation are
unchanged.
This commit is contained in:
Jose Olarte III
2026-06-26 19:26:00 +08:00
parent 9941264022
commit 4978e93711
3 changed files with 35 additions and 1 deletions

View File

@@ -18,6 +18,7 @@
C86585DF2ED456DE00824752 /* TimeSafariShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = C86585D52ED456DE00824752 /* TimeSafariShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
C8C56E142EE0474B00737D0E /* SharedImageUtility.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C56E132EE0474B00737D0E /* SharedImageUtility.swift */; };
C8C56E162EE064CB00737D0E /* SharedImagePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C56E152EE064CA00737D0E /* SharedImagePlugin.swift */; };
C8C56E182EE0700A00737D0E /* AppBridgeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8C56E172EE0700A00737D0E /* AppBridgeViewController.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -59,6 +60,7 @@
C86585E52ED4577F00824752 /* App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = App.entitlements; sourceTree = "<group>"; };
C8C56E132EE0474B00737D0E /* SharedImageUtility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedImageUtility.swift; sourceTree = "<group>"; };
C8C56E152EE064CA00737D0E /* SharedImagePlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedImagePlugin.swift; sourceTree = "<group>"; };
C8C56E172EE0700A00737D0E /* AppBridgeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppBridgeViewController.swift; sourceTree = "<group>"; };
E2E9297D5D02C549106C77F9 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = "<group>"; };
EAEC6436E595F7CD3A1C9E96 /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -127,6 +129,7 @@
504EC3061FED79650016851F /* App */ = {
isa = PBXGroup;
children = (
C8C56E172EE0700A00737D0E /* AppBridgeViewController.swift */,
C8C56E152EE064CA00737D0E /* SharedImagePlugin.swift */,
C8C56E132EE0474B00737D0E /* SharedImageUtility.swift */,
C86585E52ED4577F00824752 /* App.entitlements */,
@@ -346,6 +349,7 @@
buildActionMask = 2147483647;
files = (
C8C56E162EE064CB00737D0E /* SharedImagePlugin.swift in Sources */,
C8C56E182EE0700A00737D0E /* AppBridgeViewController.swift in Sources */,
504EC3081FED79650016851F /* AppDelegate.swift in Sources */,
C8C56E142EE0474B00737D0E /* SharedImageUtility.swift in Sources */,
);

View File

@@ -0,0 +1,30 @@
//
// AppBridgeViewController.swift
// App
//
// Capacitor bridge view controller subclass.
//
// Phase 2B-1: registers the app-local SharedImagePlugin from the deterministic
// capacitorDidLoad() lifecycle callback, where the Capacitor bridge is
// guaranteed to exist. The existing AppDelegate registration is intentionally
// left in place as a temporary safety net during this phase.
//
import UIKit
import Capacitor
class AppBridgeViewController: CAPBridgeViewController {
override func capacitorDidLoad() {
super.capacitorDidLoad()
// Register the app-local SharedImage plugin using the same approach as
// AppDelegate. The @objc(SharedImage) annotation exposes it as
// "SharedImage" to JavaScript. At this point the bridge is guaranteed
// to be available (capacitorDidLoad runs immediately after the bridge
// is created).
let pluginInstance = SharedImagePlugin()
bridge?.registerPluginInstance(pluginInstance)
print("[AppBridgeViewController] ✅ Registered SharedImagePlugin (exposed as 'SharedImage' via @objc annotation)")
}
}

View File

@@ -11,7 +11,7 @@
<!--Bridge View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="CAPBridgeViewController" customModule="Capacitor" sceneMemberID="viewController"/>
<viewController id="BYZ-38-t0r" customClass="AppBridgeViewController" customModule="App" customModuleProvider="target" sceneMemberID="viewController"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>