@capacitor/ios 8.1.0 → 8.1.1-dev-20260305T152829.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,7 +11,6 @@ public class ApplicationDelegateProxy: NSObject, UIApplicationDelegate {
11
11
  "url": url,
12
12
  "options": options
13
13
  ])
14
- NotificationCenter.default.post(name: NSNotification.Name.CDVPluginHandleOpenURL, object: url)
15
14
  lastURL = url
16
15
  return true
17
16
  }
@@ -79,9 +79,14 @@ import WebKit
79
79
  func registerPluginType(_ pluginType: CAPPlugin.Type)
80
80
  func registerPluginInstance(_ pluginInstance: CAPPlugin)
81
81
 
82
+ // MARK: - Interceptors
83
+ func registerCallInterceptor(_ name: String, handler: @escaping ([String: Any]) -> Void)
84
+
82
85
  // MARK: - View Presentation
83
86
  func showAlertWith(title: String, message: String, buttonTitle: String)
87
+ @available(*, deprecated, message: "Use self?.bridge?.viewController?.present")
84
88
  func presentVC(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)?)
89
+ @available(*, deprecated, message: "Use self?.bridge?.viewController?.dismiss")
85
90
  func dismissVC(animated flag: Bool, completion: (() -> Void)?)
86
91
  }
87
92
 
@@ -1,6 +1,5 @@
1
1
  import UIKit
2
2
  import WebKit
3
- import Cordova
4
3
 
5
4
  @objc open class CAPBridgeViewController: UIViewController {
6
5
  private var capacitorBridge: CapacitorBridge?
@@ -47,10 +46,10 @@ import Cordova
47
46
  // create the bridge
48
47
  capacitorBridge = CapacitorBridge(with: configuration,
49
48
  delegate: self,
50
- cordovaConfiguration: configDescriptor.cordovaConfiguration,
51
49
  assetHandler: assetHandler,
52
50
  delegationHandler: delegationHandler)
53
51
  capacitorDidLoad()
52
+ updateAppLocationIfNeeded()
54
53
 
55
54
  if configDescriptor.instanceType == .fixed {
56
55
  updateBinaryVersion()
@@ -89,18 +88,25 @@ import Cordova
89
88
  - Note: This is called early in the View Controller's lifecycle. Not all properties will be set at invocation.
90
89
  */
91
90
  open func instanceDescriptor() -> InstanceDescriptor {
92
- let descriptor = InstanceDescriptor.init()
93
- if !isNewBinary && !descriptor.cordovaDeployDisabled {
91
+ return InstanceDescriptor()
92
+ }
93
+
94
+ /// This function must be called after plugins are loaded or it will have no effect.
95
+ open func updateAppLocationIfNeeded() {
96
+ let cordovaPlugin = bridge?.plugin(withName: "__CordovaPlugin")
97
+ let cordovaDeployDisabled = cordovaPlugin?.perform(Selector(("cordovaDeployDisabled"))).takeUnretainedValue() as? Bool ?? false
98
+
99
+ if !isNewBinary && !cordovaDeployDisabled {
94
100
  if let persistedPath = KeyValueStore.standard["serverBasePath", as: String.self], !persistedPath.isEmpty {
95
101
  if let libPath = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true).first {
96
- descriptor.appLocation = URL(fileURLWithPath: libPath, isDirectory: true)
102
+ let serverBasePath = URL(fileURLWithPath: libPath, isDirectory: true)
97
103
  .appendingPathComponent("NoCloud")
98
104
  .appendingPathComponent("ionic_built_snapshots")
99
105
  .appendingPathComponent(URL(fileURLWithPath: persistedPath, isDirectory: true).lastPathComponent)
106
+ setServerBasePath(path: serverBasePath.path)
100
107
  }
101
108
  }
102
109
  }
103
- return descriptor
104
110
  }
105
111
 
106
112
  open func router() -> Router {
@@ -2,7 +2,7 @@
2
2
  #define CAPInstanceDescriptor_h
3
3
 
4
4
  @import UIKit;
5
- @import Cordova;
5
+
6
6
 
7
7
  typedef NS_ENUM(NSInteger, CAPInstanceType) {
8
8
  CAPInstanceTypeFixed NS_SWIFT_NAME(fixed),
@@ -137,7 +137,7 @@ NS_SWIFT_NAME(InstanceDescriptor)
137
137
  /**
138
138
  @brief The parser used to load the cofiguration for Cordova plugins.
139
139
  */
140
- @property (nonatomic, copy, nonnull) CDVConfigParser *cordovaConfiguration;
140
+ @property (nonatomic, copy, nonnull) NSObject *cordovaConfiguration;
141
141
  /**
142
142
  @brief Warnings generated during initialization.
143
143
  */
@@ -45,7 +45,6 @@ NSString* const CAPInstanceDescriptorDefaultHostname = @"localhost";
45
45
  _contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
46
46
  _appLocation = location;
47
47
  _limitsNavigationsToAppBoundDomains = FALSE;
48
- _cordovaConfiguration = [[CDVConfigParser alloc] init];
49
48
  _warnings = 0;
50
49
  if (location == nil) {
51
50
  _warnings |= CAPInstanceWarningMissingAppDir;
@@ -52,23 +52,6 @@ internal extension InstanceDescriptor {
52
52
  warnings.update(with: .missingFile)
53
53
  }
54
54
 
55
- // parse the cordova configuration
56
- var configParser: XMLParser?
57
- if let cordovaURL = cordovaURL,
58
- FileManager.default.fileExists(atPath: cordovaURL.path, isDirectory: &isDirectory),
59
- isDirectory.boolValue == false {
60
- configParser = XMLParser(contentsOf: cordovaURL)
61
- } else {
62
- warnings.update(with: .missingCordovaFile)
63
- // we don't want to break up string literals
64
- // swiftlint:disable:next line_length
65
- if let cordovaXML = "<?xml version='1.0' encoding='utf-8'?><widget version=\"1.0.0\" xmlns=\"http://www.w3.org/ns/widgets\" xmlns:cdv=\"http://cordova.apache.org/ns/1.0\"><access origin=\"*\" /></widget>".data(using: .utf8) {
66
- configParser = XMLParser(data: cordovaXML)
67
- }
68
- }
69
- configParser?.delegate = cordovaConfiguration
70
- configParser?.parse()
71
-
72
55
  // extract our configuration values
73
56
  if let config = config {
74
57
  // to be removed
@@ -160,7 +143,7 @@ internal extension InstanceDescriptor {
160
143
 
161
144
  extension InstanceDescriptor {
162
145
  @objc public var cordovaDeployDisabled: Bool {
163
- return (cordovaConfiguration.settings?["DisableDeploy".lowercased()] as? NSString)?.boolValue ?? false
146
+ return false
164
147
  }
165
148
 
166
149
  @objc public func normalize() {
@@ -1,12 +1,11 @@
1
1
  import Foundation
2
2
  import Dispatch
3
3
  import WebKit
4
- import Cordova
5
4
 
6
5
  internal typealias CapacitorPlugin = CAPPlugin & CAPBridgedPlugin
7
6
 
8
7
  struct RegistrationList: Codable {
9
- let packageClassList: Set<String>
8
+ var packageClassList: Set<String>
10
9
  }
11
10
 
12
11
  /**
@@ -93,9 +92,6 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
93
92
  }
94
93
  }
95
94
  }
96
-
97
- var tmpWindow: UIWindow?
98
- static let tmpVCAppeared = Notification(name: Notification.Name(rawValue: "tmpViewControllerAppeared"))
99
95
  public static let capacitorSite = "https://capacitorjs.com/"
100
96
  public static let fileStartIdentifier = "/_capacitor_file_"
101
97
  public static let httpInterceptorStartIdentifier = "/_capacitor_http_interceptor_"
@@ -116,18 +112,16 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
116
112
  @objc public var config: InstanceConfiguration
117
113
  // Map of all loaded and instantiated plugins by pluginId -> instance
118
114
  var plugins = [String: CapacitorPlugin]()
119
- // Manager for getting Cordova plugins
120
- var cordovaPluginManager: CDVPluginManager?
121
115
  // Calls we are storing to resolve later
122
116
  var storedCalls = ConcurrentDictionary<CAPPluginCall>()
123
117
  // Whether to inject the Cordova files
124
- private var injectCordovaFiles = false
125
- private var cordovaParser: CDVConfigParser?
118
+ private var cordovaIsPresent = false
126
119
  private var injectMiscFiles: [String] = []
127
120
  private var canInjectJS: Bool = true
128
121
 
129
122
  // Background dispatch queue for plugin calls
130
123
  open private(set) var dispatchQueue = DispatchQueue(label: "bridge")
124
+ internal private(set) var callInterceptors: [String: ([String: Any]) -> Void] = [:]
131
125
  // Array of block based observers
132
126
  var observers: [NSObjectProtocol] = []
133
127
 
@@ -204,12 +198,17 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
204
198
 
205
199
  // MARK: - Initialization
206
200
 
207
- public init(with configuration: InstanceConfiguration, delegate bridgeDelegate: CAPBridgeDelegate, cordovaConfiguration: CDVConfigParser, assetHandler: WebViewAssetHandler, delegationHandler: WebViewDelegationHandler, autoRegisterPlugins: Bool = true) {
201
+ @available(*, deprecated, renamed: "init", message: "Use different init")
202
+ public convenience init(with configuration: InstanceConfiguration, delegate bridgeDelegate: CAPBridgeDelegate, cordovaConfiguration: Any, assetHandler: WebViewAssetHandler, delegationHandler: WebViewDelegationHandler, autoRegisterPlugins: Bool = true) {
203
+ self.init(with: configuration, delegate: bridgeDelegate, assetHandler: assetHandler, delegationHandler: delegationHandler, autoRegisterPlugins: autoRegisterPlugins)
204
+ }
205
+
206
+ public init(with configuration: InstanceConfiguration, delegate bridgeDelegate: CAPBridgeDelegate, assetHandler: WebViewAssetHandler, delegationHandler: WebViewDelegationHandler, autoRegisterPlugins: Bool = true) {
207
+
208
208
  self.bridgeDelegate = bridgeDelegate
209
209
  self.webViewAssetHandler = assetHandler
210
210
  self.webViewDelegationHandler = delegationHandler
211
211
  self.config = configuration
212
- self.cordovaParser = cordovaConfiguration
213
212
  self.notificationRouter = NotificationRouter()
214
213
  self.notificationRouter.handleApplicationNotifications = configuration.handleApplicationNotifications
215
214
  self.autoRegisterPlugins = autoRegisterPlugins
@@ -219,12 +218,9 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
219
218
 
220
219
  exportCoreJS(localUrl: configuration.localURL.absoluteString)
221
220
  registerPlugins()
222
- setupCordovaCompatibility()
221
+ setupListeners()
223
222
  exportMiscJS()
224
223
  canInjectJS = false
225
- observers.append(NotificationCenter.default.addObserver(forName: type(of: self).tmpVCAppeared.name, object: .none, queue: .none) { [weak self] _ in
226
- self?.tmpWindow = nil
227
- })
228
224
 
229
225
  self.setupWebDebugging(configuration: configuration)
230
226
  }
@@ -261,31 +257,27 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
261
257
  injectMiscFiles.removeAll()
262
258
  }
263
259
 
264
- /**
265
- Set up our Cordova compat by loading all known Cordova plugins and injecting their JS.
266
- */
267
- func setupCordovaCompatibility() {
268
- if injectCordovaFiles {
269
- exportCordovaJS()
270
- registerCordovaPlugins()
271
- } else {
272
- observers.append(NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: OperationQueue.main) { [weak self] (_) in
273
- self?.triggerDocumentJSEvent(eventName: "resume")
274
- })
275
- observers.append(NotificationCenter.default.addObserver(forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: OperationQueue.main) { [weak self] (_) in
276
- self?.triggerDocumentJSEvent(eventName: "pause")
277
- })
278
- }
279
- }
280
-
281
- /**
282
- Export the core Cordova JS runtime
283
- */
284
- func exportCordovaJS() {
285
- do {
286
- try JSExport.exportCordovaJS(userContentController: webViewDelegationHandler.contentController)
287
- } catch {
288
- type(of: self).fatalError(error, error)
260
+ func setupListeners() {
261
+ if !cordovaIsPresent {
262
+ observers.append(
263
+ NotificationCenter.default.addObserver(
264
+ forName: UIApplication.willEnterForegroundNotification,
265
+ object: nil,
266
+ queue: .main
267
+ ) { [weak self] _ in
268
+ self?.triggerDocumentJSEvent(eventName: "resume")
269
+ }
270
+ )
271
+
272
+ observers.append(
273
+ NotificationCenter.default.addObserver(
274
+ forName: UIApplication.didEnterBackgroundNotification,
275
+ object: nil,
276
+ queue: .main
277
+ ) { [weak self] _ in
278
+ self?.triggerDocumentJSEvent(eventName: "pause")
279
+ }
280
+ )
289
281
  }
290
282
  }
291
283
 
@@ -308,14 +300,13 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
308
300
  do {
309
301
  if let pluginJSON = Bundle.main.url(forResource: "capacitor.config", withExtension: "json") {
310
302
  let pluginData = try Data(contentsOf: pluginJSON)
311
- let registrationList = try JSONDecoder().decode(RegistrationList.self, from: pluginData)
303
+ var registrationList = try JSONDecoder().decode(RegistrationList.self, from: pluginData)
312
304
 
313
305
  for plugin in registrationList.packageClassList {
314
- if let pluginClass = NSClassFromString(plugin) {
315
- if pluginClass == CDVPlugin.self {
316
- injectCordovaFiles = true
317
- } else {
318
- pluginList.append(pluginClass)
306
+ if let pluginClass = NSClassFromString(plugin), pluginClass is CAPPlugin.Type {
307
+ pluginList.append(pluginClass)
308
+ if plugin == "CordovaPlugin" {
309
+ cordovaIsPresent = true
319
310
  }
320
311
  }
321
312
  }
@@ -392,6 +383,10 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
392
383
 
393
384
  // MARK: - CAPBridgeProtocol: Call Management
394
385
 
386
+ public func registerCallInterceptor(_ name: String, handler: @escaping ([String: Any]) -> Void) {
387
+ callInterceptors[name] = handler
388
+ }
389
+
395
390
  @objc public func saveCall(_ call: CAPPluginCall) {
396
391
  storedCalls[call.callbackId] = call
397
392
  }
@@ -424,23 +419,6 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
424
419
  return self.dispatchQueue
425
420
  }
426
421
 
427
- func registerCordovaPlugins() {
428
- guard let cordovaParser = cordovaParser else {
429
- return
430
- }
431
- cordovaPluginManager = CDVPluginManager.init(parser: cordovaParser, viewController: self.viewController, webView: self.getWebView())
432
- if cordovaParser.startupPluginNames.count > 0 {
433
- for pluginName in cordovaParser.startupPluginNames {
434
- _ = cordovaPluginManager?.getCommandInstance(pluginName as? String)
435
- }
436
- }
437
- do {
438
- try JSExport.exportCordovaPluginsJS(userContentController: webViewDelegationHandler.contentController)
439
- } catch {
440
- type(of: self).fatalError(error, error)
441
- }
442
- }
443
-
444
422
  func reload() {
445
423
  self.getWebView()?.reload()
446
424
  }
@@ -539,34 +517,6 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
539
517
  }
540
518
  }
541
519
 
542
- /**
543
- Handle a Cordova call from JavaScript. First, find the corresponding plugin,
544
- construct a selector, and perform that selector on the plugin instance.
545
- */
546
- func handleCordovaJSCall(call: JSCall) {
547
- // Create a selector to send to the plugin
548
-
549
- if let plugin = self.cordovaPluginManager?.getCommandInstance(call.pluginId.lowercased()) {
550
- let selector = NSSelectorFromString("\(call.method):")
551
- if !plugin.responds(to: selector) {
552
- CAPLog.print("Error: Plugin \(plugin.className ?? "") does not respond to method call \(selector).")
553
- CAPLog.print("Ensure plugin method exists and uses @objc in its declaration")
554
- return
555
- }
556
-
557
- let arguments: [Any] = call.options["options"] as? [Any] ?? []
558
- let pluginCall = CDVInvokedUrlCommand(arguments: arguments,
559
- callbackId: call.callbackId,
560
- className: plugin.className,
561
- methodName: call.method)
562
- plugin.perform(selector, with: pluginCall)
563
-
564
- } else {
565
- CAPLog.print("Error: Cordova Plugin mapping not found")
566
- return
567
- }
568
- }
569
-
570
520
  func removeAllPluginListeners() {
571
521
  for plugin in plugins.values {
572
522
  plugin.perform(#selector(CAPPlugin.removeAllListeners(_:)), with: nil)
@@ -747,22 +697,10 @@ open class CapacitorBridge: NSObject, CAPBridgeProtocol {
747
697
  }
748
698
 
749
699
  @objc open func presentVC(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
750
- if viewControllerToPresent.modalPresentationStyle == .popover {
751
- self.viewController?.present(viewControllerToPresent, animated: flag, completion: completion)
752
- } else {
753
- self.tmpWindow = UIWindow.init(frame: UIScreen.main.bounds)
754
- self.tmpWindow?.rootViewController = TmpViewController.init()
755
- self.tmpWindow?.makeKeyAndVisible()
756
- self.tmpWindow?.rootViewController?.present(viewControllerToPresent, animated: flag, completion: completion)
757
- }
700
+ self.viewController?.present(viewControllerToPresent, animated: flag, completion: completion)
758
701
  }
759
702
 
760
703
  @objc open func dismissVC(animated flag: Bool, completion: (() -> Void)? = nil) {
761
- if self.tmpWindow == nil {
762
- self.viewController?.dismiss(animated: flag, completion: completion)
763
- } else {
764
- self.tmpWindow?.rootViewController?.dismiss(animated: flag, completion: completion)
765
- self.tmpWindow = nil
766
- }
704
+ self.viewController?.dismiss(animated: flag, completion: completion)
767
705
  }
768
706
  }
@@ -14,11 +14,11 @@ public typealias JSResultBody = [String: Any]
14
14
  /**
15
15
  * A call originating from JavaScript land
16
16
  */
17
- internal struct JSCall {
18
- let options: [String: Any]
19
- let pluginId: String
20
- let method: String
21
- let callbackId: String
17
+ public struct JSCall {
18
+ public let options: [String: Any]
19
+ public let pluginId: String
20
+ public let method: String
21
+ public let callbackId: String
22
22
  }
23
23
 
24
24
  internal protocol JSResultProtocol {
@@ -35,24 +35,6 @@ internal class JSExport {
35
35
  }
36
36
  }
37
37
 
38
- static func exportCordovaJS(userContentController: WKUserContentController) throws {
39
- guard let cordovaUrl = Bundle.main.url(forResource: "public/cordova", withExtension: "js") else {
40
- CAPLog.print("ERROR: Required cordova.js file not found. Cordova plugins will not function!")
41
- throw CapacitorBridgeError.errorExportingCoreJS
42
- }
43
- guard let cordovaPluginsUrl = Bundle.main.url(forResource: "public/cordova_plugins", withExtension: "js") else {
44
- CAPLog.print("ERROR: Required cordova_plugins.js file not found. Cordova plugins will not function!")
45
- throw CapacitorBridgeError.errorExportingCoreJS
46
- }
47
- do {
48
- try self.injectFile(fileURL: cordovaUrl, userContentController: userContentController)
49
- try self.injectFile(fileURL: cordovaPluginsUrl, userContentController: userContentController)
50
- } catch {
51
- CAPLog.print("ERROR: Unable to read required cordova files. Cordova plugins will not function!")
52
- throw CapacitorBridgeError.errorExportingCoreJS
53
- }
54
- }
55
-
56
38
  static func exportMiscFileJS(paths: [String], userContentController: WKUserContentController) {
57
39
  for path in paths {
58
40
  if let miscJSFilePath = Bundle.main.url(forResource: "public/\(path.replacingOccurrences(of: ".js", with: ""))", withExtension: "js") {
@@ -184,28 +166,6 @@ internal class JSExport {
184
166
  return lines.joined(separator: "\n")
185
167
  }
186
168
 
187
- static func exportCordovaPluginsJS(userContentController: WKUserContentController) throws {
188
- if let pluginsJSFolder = Bundle.main.url(forResource: "public/plugins", withExtension: nil) {
189
- self.injectFilesForFolder(folder: pluginsJSFolder, userContentController: userContentController)
190
- }
191
- }
192
-
193
- static func injectFilesForFolder(folder: URL, userContentController: WKUserContentController) {
194
- let fileManager = FileManager.default
195
- do {
196
- let fileURLs = try fileManager.contentsOfDirectory(at: folder, includingPropertiesForKeys: nil, options: [])
197
- for fileURL in fileURLs {
198
- if fileURL.hasDirectoryPath {
199
- injectFilesForFolder(folder: fileURL, userContentController: userContentController)
200
- } else {
201
- try self.injectFile(fileURL: fileURL, userContentController: userContentController)
202
- }
203
- }
204
- } catch {
205
- CAPLog.print("Error while enumerating files")
206
- }
207
- }
208
-
209
169
  static func injectFile(fileURL: URL, userContentController: WKUserContentController) throws {
210
170
  do {
211
171
  let data = try String(contentsOf: fileURL, encoding: .utf8)
@@ -208,17 +208,8 @@ open class WebViewDelegationHandler: NSObject, WKNavigationDelegate, WKUIDelegat
208
208
  }
209
209
 
210
210
  bridge.handleJSCall(call: JSCall(options: options, pluginId: pluginId, method: method, callbackId: callbackId))
211
- } else if type == "cordova" {
212
- let pluginId = dict["service"] as? String ?? ""
213
- let method = dict["action"] as? String ?? ""
214
- let callbackId = dict["callbackId"] as? String ?? ""
215
-
216
- let args = dict["actionArgs"] as? Array ?? []
217
- let options = ["options": args]
218
-
219
- CAPLog.print("To Native Cordova -> ", pluginId, method, callbackId, options)
220
-
221
- bridge.handleCordovaJSCall(call: JSCall(options: options, pluginId: pluginId, method: method, callbackId: callbackId))
211
+ } else if let handler = bridge.callInterceptors[type] {
212
+ handler(dict)
222
213
  }
223
214
  }
224
215
  }
package/Capacitor.podspec CHANGED
@@ -19,6 +19,5 @@ Pod::Spec.new do |s|
19
19
  s.module_map = "#{prefix}Capacitor/Capacitor/Capacitor.modulemap"
20
20
  s.resources = ["#{prefix}Capacitor/Capacitor/assets/native-bridge.js"]
21
21
  s.resource_bundles = { 'Capacitor' => ["#{prefix}Capacitor/Capacitor/PrivacyInfo.xcprivacy"] }
22
- s.dependency 'CapacitorCordova'
23
22
  s.swift_version = '5.1'
24
23
  end
@@ -0,0 +1,126 @@
1
+ import Capacitor
2
+
3
+ @objc(CordovaPlugin)
4
+ public class CordovaPlugin: CAPPlugin, CAPBridgedPlugin {
5
+ public let jsName = "__CordovaPlugin"
6
+ public let pluginMethods: [CAPPluginMethod] = []
7
+ public var identifier: String { jsName }
8
+
9
+ private var _cordovaDeployDisabled = false
10
+
11
+ override public func load() {
12
+ injectJavascript()
13
+ configureRuntime()
14
+ }
15
+
16
+ func configureRuntime() {
17
+ guard let configURL = Bundle.main.url(forResource: "config", withExtension: "xml") else { fatalError() }
18
+ guard let bridge, let webView = bridge.webView else { return }
19
+
20
+ let cordovaConfigParser = CDVConfigParser()
21
+
22
+ let xmlParser = XMLParser(contentsOf: configURL)
23
+ xmlParser?.delegate = cordovaConfigParser
24
+ xmlParser?.parse()
25
+
26
+ guard let pluginManager = CDVPluginManager(
27
+ parser: cordovaConfigParser,
28
+ viewController: bridge.viewController,
29
+ webView: bridge.webView
30
+ ) else { return }
31
+
32
+ for plugin in cordovaConfigParser.startupPluginNames.compactMap({ $0 as? String }) {
33
+ _ = pluginManager.getCommandInstance(plugin)
34
+ }
35
+
36
+ exportCordovaPluginsJS(userContentController: webView.configuration.userContentController)
37
+
38
+ bridge.registerCallInterceptor("cordova") { [pluginManager] dict in
39
+ let pluginId = dict["service"] as? String ?? ""
40
+ let method = dict["action"] as? String ?? ""
41
+ let callbackId = dict["callbackId"] as? String ?? ""
42
+
43
+ let args = dict["actionArgs"] as? Array ?? []
44
+ let options = ["options": args]
45
+
46
+ CAPLog.print("To Native Cordova -> ", pluginId, method, callbackId, options)
47
+
48
+ if let plugin = pluginManager.getCommandInstance(pluginId.lowercased()) {
49
+ let selector = NSSelectorFromString("\(method):")
50
+ if !plugin.responds(to: selector) {
51
+ CAPLog.print("Error: Plugin \(plugin.className ?? "") does not respond to method call \(selector).")
52
+ CAPLog.print("Ensure plugin method exists and uses @objc in its declaration")
53
+ return
54
+ }
55
+
56
+ let arguments = options["options"] ?? []
57
+ let pluginCall = CDVInvokedUrlCommand(
58
+ arguments: arguments,
59
+ callbackId: callbackId,
60
+ className: plugin.className,
61
+ methodName: method
62
+ )
63
+
64
+ plugin.perform(selector, with: pluginCall)
65
+
66
+ } else {
67
+ CAPLog.print("Error: Cordova Plugin mapping not found")
68
+ return
69
+ }
70
+ }
71
+
72
+ _cordovaDeployDisabled = (cordovaConfigParser.settings?["DisableDeploy".lowercased()] as? NSString)?.boolValue ?? false
73
+ }
74
+
75
+ @objc
76
+ func cordovaDeployDisabled() -> NSNumber {
77
+ return _cordovaDeployDisabled as NSNumber
78
+ }
79
+
80
+ func injectJavascript() {
81
+ guard let cordovaUrl = Bundle.main.url(forResource: "public/cordova", withExtension: "js") else {
82
+ fatalError("ERROR: Required cordova.js file not found. Cordova plugins will not function!")
83
+ }
84
+
85
+ guard let cordovaPluginsUrl = Bundle.main.url(forResource: "public/cordova_plugins", withExtension: "js") else {
86
+ fatalError("ERROR: Required cordova_plugins.js file not found. Cordova plugins will not function!")
87
+ }
88
+
89
+ guard let webView = bridge?.webView else { return }
90
+
91
+ injectFile(fileURL: cordovaUrl, userContentController: webView.configuration.userContentController)
92
+ injectFile(fileURL: cordovaPluginsUrl, userContentController: webView.configuration.userContentController)
93
+ }
94
+
95
+ func exportCordovaPluginsJS(userContentController: WKUserContentController) {
96
+ if let pluginsJSFolder = Bundle.main.url(forResource: "public/plugins", withExtension: nil) {
97
+ injectFilesForFolder(folder: pluginsJSFolder, userContentController: userContentController)
98
+ }
99
+ }
100
+
101
+ func injectFile(fileURL: URL, userContentController: WKUserContentController) {
102
+ do {
103
+ let data = try String(contentsOf: fileURL, encoding: .utf8)
104
+ let userScript = WKUserScript(source: data, injectionTime: .atDocumentStart, forMainFrameOnly: true)
105
+ userContentController.addUserScript(userScript)
106
+ } catch {
107
+ fatalError("Unable to inject js file")
108
+ }
109
+ }
110
+
111
+ func injectFilesForFolder(folder: URL, userContentController: WKUserContentController) {
112
+ let fileManager = FileManager.default
113
+ do {
114
+ let fileURLs = try fileManager.contentsOfDirectory(at: folder, includingPropertiesForKeys: nil, options: [])
115
+ for fileURL in fileURLs {
116
+ if fileURL.hasDirectoryPath {
117
+ injectFilesForFolder(folder: fileURL, userContentController: userContentController)
118
+ } else {
119
+ injectFile(fileURL: fileURL, userContentController: userContentController)
120
+ }
121
+ }
122
+ } catch {
123
+ CAPLog.print("Error while enumerating files")
124
+ }
125
+ }
126
+ }
@@ -16,11 +16,12 @@ Pod::Spec.new do |s|
16
16
  s.authors = { 'Ionic Team' => 'hi@ionicframework.com' }
17
17
  s.source = { git: 'https://github.com/ionic-team/capacitor', tag: s.version.to_s }
18
18
  s.platform = :ios, 15.0
19
- s.source_files = "#{prefix}CapacitorCordova/CapacitorCordova/**/*.{h,m}"
19
+ s.source_files = "#{prefix}CapacitorCordova/CapacitorCordova/**/*.{h,m,swift}"
20
20
  s.public_header_files = "#{prefix}CapacitorCordova/CapacitorCordova/Classes/Public/*.h",
21
21
  "#{prefix}CapacitorCordova/CapacitorCordova/CapacitorCordova.h"
22
22
  s.module_map = "#{prefix}CapacitorCordova/CapacitorCordova/CapacitorCordova.modulemap"
23
23
  s.resource_bundles = { 'CapacitorCordova' => ["#{prefix}CapacitorCordova/CapacitorCordova/PrivacyInfo.xcprivacy"] }
24
24
  s.requires_arc = true
25
+ s.dependency 'Capacitor', s.version.to_s
25
26
  s.framework = 'WebKit'
26
27
  end
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capacitor/ios",
3
- "version": "8.1.0",
3
+ "version": "8.1.1-dev-20260305T152829.0",
4
4
  "description": "Capacitor: Cross-platform apps with JavaScript and the web",
5
5
  "homepage": "https://capacitorjs.com",
6
6
  "author": "Ionic Team <hi@ionic.io> (https://ionic.io)",
@@ -25,7 +25,7 @@
25
25
  "xc:build:CapacitorCordova": "cd CapacitorCordova && xcodebuild && cd .."
26
26
  },
27
27
  "peerDependencies": {
28
- "@capacitor/core": "^8.1.0"
28
+ "@capacitor/core": "^8.1.0-dev-20260305T152829.0"
29
29
  },
30
30
  "publishConfig": {
31
31
  "access": "public"
@@ -1,6 +0,0 @@
1
- #import <Capacitor/Capacitor-Swift.h>
2
-
3
- @interface CAPBridgeViewController (CDVScreenOrientationDelegate) <CDVScreenOrientationDelegate>
4
-
5
- @end
6
-
@@ -1,5 +0,0 @@
1
- #import "CAPBridgeViewController+CDVScreenOrientationDelegate.h"
2
-
3
- @implementation CAPBridgeViewController (CDVScreenOrientationDelegate)
4
-
5
- @end
@@ -1,8 +0,0 @@
1
- import UIKit
2
-
3
- internal class TmpViewController: UIViewController {
4
- override func viewDidAppear(_ animated: Bool) {
5
- super.viewDidAppear(animated)
6
- NotificationCenter.default.post(CapacitorBridge.tmpVCAppeared)
7
- }
8
- }