diff --git a/SalesforceHybridSDK.podspec b/SalesforceHybridSDK.podspec index e5d21403..fa4d817c 100644 --- a/SalesforceHybridSDK.podspec +++ b/SalesforceHybridSDK.podspec @@ -13,7 +13,7 @@ Pod::Spec.new do |s| s.default_subspec = 'SalesforceHybridSDK' s.subspec 'SalesforceHybridSDK' do |sdkhybrid| sdkhybrid.dependency 'MobileSync', "~>#{s.version}" - sdkhybrid.dependency 'Cordova', '7.1.1' + sdkhybrid.dependency 'Cordova', '8.1.0' sdkhybrid.resource_bundles = { 'SalesforceHybridSDK' => [ 'libs/SalesforceHybridSDK/SalesforceHybridSDK/PrivacyInfo.xcprivacy' ] } sdkhybrid.source_files = 'libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/**/*.{h,m,swift}', 'libs/SalesforceHybridSDK/SalesforceHybridSDK/SalesforceHybridSDK.h' sdkhybrid.public_header_files = 'libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/Plugins/SFAdditions/CDVPlugin+SFAdditions.h', 'libs/SalesforceHybridSDK/SalesforceHybridSDK/SalesforceHybridSDK.h', 'libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/SalesforceHybridSDKManager.h', 'libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/Plugins/SFOAuthPlugin/SalesforceOAuthPlugin.h', 'libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/Plugins/SFAccountManagerPlugin/SFAccountManagerPlugin.h', 'libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/Plugins/SFForcePlugin/SFForcePlugin.h', 'libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/SFHybridViewConfig.h', 'libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/SFHybridViewController.h', 'libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/SFLocalhostSubstitutionCache.h', 'libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/Plugins/SFMobileSyncPlugin/SFMobileSyncPlugin.h', 'libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/Plugins/SFNetworkPlugin/SFNetworkPlugin.h', 'libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/SFSDKHybridLogger.h', 'libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/Plugins/SDKInfo/SFSDKInfoPlugin.h', 'libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/Plugins/SFSmartStore/SFSmartStorePlugin.h' diff --git a/docs/hybrid/README.md b/docs/hybrid/README.md index ac2de8df..25cc65ce 100644 --- a/docs/hybrid/README.md +++ b/docs/hybrid/README.md @@ -47,15 +47,22 @@ The `shared/hybrid/` directory contains Objective-C files that `tools/update.sh` | File | Role | |------|------| -| `AppDelegate.m` | Application entry point that bootstraps the Salesforce hybrid runtime (OAuth, SDK initialization, view controller setup) | +| `AppDelegate.swift` | Application entry point — bootstraps the Salesforce hybrid runtime (SDK init, OAuth, URL cache, view controller setup). Uses `@main @_objcImplementation extension AppDelegate` pattern required by cordova-ios 8.x. | | `InitialViewController.h` / `.m` | Root view controller displayed before the Cordova WKWebView loads | | `UIApplication+SalesforceHybridSDK.h` / `.m` | UIApplication category that tracks last-event timing for passcode inactivity | -The directory also contains `config.xml` and `cordova_plugins.js`, but only the Objective-C files are copied to the CordovaPlugin. +The directory also contains `config.xml` and `cordova_plugins.js`, but only the Swift/ObjC source files are copied to the CordovaPlugin. -### Why `AppDelegate.m` lives here +### Why `AppDelegate.swift` lives here and how it reaches the generated app -When `cordova platform add ios` runs, Cordova generates its own `AppDelegate.m`. The CordovaPlugin's `postinstall-ios.js` hook patches `project.pbxproj` to redirect the AppDelegate reference to `Plugins/com.salesforce/AppDelegate.m` — the SDK version that initializes the Salesforce hybrid runtime (OAuth, SDK manager, hybrid view controller). Without this patch, none of the Salesforce Cordova plugins would function. +When `cordova platform add ios` runs, Cordova generates its own `AppDelegate.swift`. The CordovaPlugin's `postinstall-ios.js` hook: +1. Copies our `AppDelegate.swift` from the plugin into `platforms/ios/App/Plugins/com.salesforce/` +2. Patches `project.pbxproj` to redirect the app target's `AppDelegate.swift` reference to `Plugins/com.salesforce/AppDelegate.swift` +3. Adds `#import "InitialViewController.h"` to the Bridging-Header so the ObjC class is accessible from Swift + +Without this, Cordova's bare `AppDelegate.swift` would be used and the Salesforce SDK would never initialize. + +**Note:** `AppDelegate.swift` is intentionally **not** declared as a `` in `plugin.xml`. In cordova-ios 8.x, `` entries go into the `CordovaPlugins` SPM target, which cannot link CocoaPods frameworks like `SalesforceHybridSDK`. The copy + redirect approach is the correct workaround. --- @@ -77,10 +84,38 @@ Other submodules: Located under `hybrid/SampleApps/`: -- **AccountEditor** — Basic CRUD operations on Account records using Cordova plugins -- **MobileSyncExplorerHybrid** — Full MobileSync demo with offline sync and conflict resolution +- **AccountEditor** — Basic CRUD operations on Account records using Cordova plugins and `force.js` +- **MobileSyncExplorerHybrid** — Full offline sync demo using SmartStore and MobileSync + +### How sample apps are structured + +The sample apps are standard Xcode projects that wire together files from four sources via relative paths in `project.pbxproj`: + +| Source | What it provides | +|--------|-----------------| +| `external/shared/samples//` | App HTML, CSS, JS, `bootconfig.json`, sync configs (from Shared submodule) | +| `external/shared/gen/plugins_with_define/` | Cordova plugin JS files copied to `www/plugins/com.salesforce/` (from Shared submodule) | +| `shared/hybrid/` | `AppDelegate.swift`, `InitialViewController.{h,m}`, `UIApplication+SalesforceHybridSDK.{h,m}`, `config.xml`, `cordova_plugins.js` | +| `external/cordova/` | `cordova.js`, `CDVAppDelegate.{h,m}`, `CordovaLib.xcodeproj` (from cordova submodule) | +| `external/SalesforceMobileSDK-iOS/` | SDK library `.xcodeproj` files and shared resources (from iOS SDK submodule) | + +None of the app-specific source files live in the `hybrid/SampleApps/` directory itself — the Xcode projects are essentially just wiring. All content is pulled from submodules and `shared/hybrid/`. + +### Building the sample apps + +Prerequisites: run `./install.sh` from the repo root to populate all external submodules. + +```bash +# Open the workspace (not individual .xcodeproj files) +open SalesforceMobileSDK-Hybrid.xcworkspace +``` + +Select the `AccountEditor` or `MobileSyncExplorerHybrid` scheme and build. Before running: +- Fill in your Connected App credentials in `external/shared/samples//bootconfig.json` + +### Cordova version dependency -Their JavaScript source comes from the `external/shared/` submodule. +The sample apps link directly against `external/cordova/CordovaLib/CordovaLib.xcodeproj` (the cordova submodule, currently cordova-ios 7.1.1). When the cordova-ios version is upgraded, the `external/cordova` submodule must be updated to the new version. This also requires updating the sample app Xcode projects to reflect any project structure changes in the new Cordova template (e.g., the cordova-ios 8.x move from `main.m` + ObjC `AppDelegate.m` to a Swift `AppDelegate.swift` with `@main`). --- diff --git a/external/cordova b/external/cordova index 9b74d457..e1abace8 160000 --- a/external/cordova +++ b/external/cordova @@ -1 +1 @@ -Subproject commit 9b74d4576b5d5aca769f99e266e88e04154b1f61 +Subproject commit e1abace870796357d4bae063c17f752dd2952c01 diff --git a/hybrid/SampleApps/AccountEditor/AccountEditor.xcodeproj/project.pbxproj b/hybrid/SampleApps/AccountEditor/AccountEditor.xcodeproj/project.pbxproj index 3cbd75d5..3b30683a 100644 --- a/hybrid/SampleApps/AccountEditor/AccountEditor.xcodeproj/project.pbxproj +++ b/hybrid/SampleApps/AccountEditor/AccountEditor.xcodeproj/project.pbxproj @@ -19,7 +19,7 @@ 4F6D68EC228E3129008C8A96 /* SalesforceHybridSDK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4FFEE5FE1BFE912300B7AA8A /* SalesforceHybridSDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 4F6D68F0228E3129008C8A96 /* Cordova.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEEF967C1EB7CE5A0059CA79 /* Cordova.framework */; }; 4F6D68F1228E3129008C8A96 /* Cordova.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CEEF967C1EB7CE5A0059CA79 /* Cordova.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 4F6D839B19525B66003EBB16 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4F6D839819525B66003EBB16 /* AppDelegate.m */; }; + 4F6D839B19525B66003EBB16 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F6D839819525B66003EBB16 /* AppDelegate.swift */; }; 4FD3FC441DB05B2600646D6D /* force+promise.js in Copy js Files */ = {isa = PBXBuildFile; fileRef = 4FD3FC1F1DB05B1E00646D6D /* force+promise.js */; }; 4FF15E871908856800705FE0 /* AccountEditor.html in Copy Shared www Files */ = {isa = PBXBuildFile; fileRef = 4FF15E2A190884FE00705FE0 /* AccountEditor.html */; }; 4FF15E881908856800705FE0 /* bootconfig.json in Copy Shared www Files */ = {isa = PBXBuildFile; fileRef = 4FF15E2B190884FE00705FE0 /* bootconfig.json */; }; @@ -50,7 +50,6 @@ 824A9BD41721FCA400C9BD79 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 824A9BD31721FCA400C9BD79 /* Foundation.framework */; }; 824A9BD61721FCA400C9BD79 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 824A9BD51721FCA400C9BD79 /* CoreGraphics.framework */; }; 824A9BDC1721FCA400C9BD79 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 824A9BDA1721FCA400C9BD79 /* InfoPlist.strings */; }; - 824A9BDE1721FCA400C9BD79 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 824A9BDD1721FCA400C9BD79 /* main.m */; }; 824A9DA91724C99800C9BD79 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 824A9DA81724C99800C9BD79 /* AudioToolbox.framework */; }; 824A9DAB1724C9C900C9BD79 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 824A9DAA1724C9C900C9BD79 /* AVFoundation.framework */; }; 824A9DAD1724C9D100C9BD79 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 824A9DAC1724C9D100C9BD79 /* CFNetwork.framework */; }; @@ -87,8 +86,7 @@ CE7BA1E91D8CB330000B91D7 /* com.salesforce.plugin.mobilesync.js in Copy plugins Files */ = {isa = PBXBuildFile; fileRef = CE7BA1BB1D8CA3DF000B91D7 /* com.salesforce.plugin.mobilesync.js */; }; CE7BA1EA1D8CB330000B91D7 /* com.salesforce.util.push.js in Copy plugins Files */ = {isa = PBXBuildFile; fileRef = CE7BA1BC1D8CA3DF000B91D7 /* com.salesforce.util.push.js */; }; CEBDA0891D3C052600DBDBD0 /* CDVAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBDA0881D3C052600DBDBD0 /* CDVAppDelegate.m */; }; - CEBDA0B21D3C059900DBDBD0 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBDA0B01D3C059900DBDBD0 /* MainViewController.m */; }; - CEBDA0B31D3C059900DBDBD0 /* MainViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEBDA0B11D3C059900DBDBD0 /* MainViewController.xib */; }; + A1B2C3D4E5F6A7B8C9D0E1F3 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F6A7B8C9D0E1F2 /* ViewController.swift */; }; CED747481E8C86EB0019AA9D /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CED747471E8C86EB0019AA9D /* WebKit.framework */; }; /* End PBXBuildFile section */ @@ -390,8 +388,8 @@ 4F5B96151DA8695E001627F2 /* force.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = force.js; sourceTree = ""; }; 4F5B966C1DAD9E90001627F2 /* com.salesforce.plugin.smartstore.client.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = com.salesforce.plugin.smartstore.client.js; sourceTree = ""; }; 4F5B966D1DAD9E90001627F2 /* com.salesforce.util.promiser.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = com.salesforce.util.promiser.js; sourceTree = ""; }; - 4F6D839819525B66003EBB16 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = ../../../../shared/hybrid/AppDelegate.m; sourceTree = ""; }; - 4F6D839919525B66003EBB16 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = ../../../../external/cordova/templates/project/__PROJECT_NAME__/AppDelegate.h; sourceTree = ""; }; + 4F6D839819525B66003EBB16 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = ../../../../shared/hybrid/AppDelegate.swift; sourceTree = ""; }; + 4F6D839919525B66003EBB16 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = ../../../../external/cordova/templates/project/App/AppDelegate.h; sourceTree = ""; }; 4FD3FC1F1DB05B1E00646D6D /* force+promise.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = "force+promise.js"; path = "../../../libs/force+promise.js"; sourceTree = ""; }; 4FF15E25190884C600705FE0 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; }; 4FF15E2A190884FE00705FE0 /* AccountEditor.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = AccountEditor.html; path = ../../../../external/shared/samples/accounteditor/AccountEditor.html; sourceTree = ""; }; @@ -423,7 +421,6 @@ 824A9BD51721FCA400C9BD79 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 824A9BD91721FCA400C9BD79 /* AccountEditor-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "AccountEditor-Info.plist"; sourceTree = ""; }; 824A9BDB1721FCA400C9BD79 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 824A9BDD1721FCA400C9BD79 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ../../../../external/cordova/templates/project/__PROJECT_NAME__/main.m; sourceTree = ""; }; 824A9BDF1721FCA400C9BD79 /* AccountEditor-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AccountEditor-Prefix.pch"; sourceTree = ""; }; 824A9BF91721FE1100C9BD79 /* readme.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = readme.md; sourceTree = ""; }; 824A9DA41724C98900C9BD79 /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; }; @@ -470,9 +467,8 @@ CE7BA1BC1D8CA3DF000B91D7 /* com.salesforce.util.push.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = com.salesforce.util.push.js; sourceTree = ""; }; CEBDA0871D3C052600DBDBD0 /* CDVAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVAppDelegate.h; path = ../../../../external/cordova/CordovaLib/include/Cordova/CDVAppDelegate.h; sourceTree = ""; }; CEBDA0881D3C052600DBDBD0 /* CDVAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVAppDelegate.m; path = ../../../../external/cordova/CordovaLib/Classes/Public/CDVAppDelegate.m; sourceTree = ""; }; - CEBDA0AF1D3C059900DBDBD0 /* MainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MainViewController.h; path = ../../../../external/cordova/templates/project/__PROJECT_NAME__/MainViewController.h; sourceTree = ""; }; - CEBDA0B01D3C059900DBDBD0 /* MainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MainViewController.m; path = ../../../../external/cordova/templates/project/__PROJECT_NAME__/MainViewController.m; sourceTree = ""; }; - CEBDA0B11D3C059900DBDBD0 /* MainViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = MainViewController.xib; path = ../../../../external/cordova/templates/project/__PROJECT_NAME__/MainViewController.xib; sourceTree = ""; }; + A1B2C3D4E5F6A7B8C9D0E1F2 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ViewController.swift; path = ../../../../external/cordova/templates/project/App/ViewController.swift; sourceTree = ""; }; + CEBDA0AF1D3C059900DBDBD0 /* MainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MainViewController.h; path = ../../../../external/cordova/templates/project/App/MainViewController.h; sourceTree = ""; }; CED747471E8C86EB0019AA9D /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; CEEF96741EB7CE5A0059CA79 /* CordovaLib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CordovaLib.xcodeproj; path = ../../../external/cordova/CordovaLib/CordovaLib.xcodeproj; sourceTree = ""; }; /* End PBXFileReference section */ @@ -663,7 +659,6 @@ 824A9DC01724CE4600C9BD79 /* config.xml */, 824A9BD91721FCA400C9BD79 /* AccountEditor-Info.plist */, 824A9BDA1721FCA400C9BD79 /* InfoPlist.strings */, - 824A9BDD1721FCA400C9BD79 /* main.m */, 824A9BDF1721FCA400C9BD79 /* AccountEditor-Prefix.pch */, 69B48BEE2AD4DE1C0026AEC6 /* PrivacyInfo.xcprivacy */, ); @@ -698,11 +693,10 @@ children = ( B7BAD75F1FBB7DEE0046629F /* IDPLoginViewController.xib */, CEBDA0AF1D3C059900DBDBD0 /* MainViewController.h */, - CEBDA0B01D3C059900DBDBD0 /* MainViewController.m */, - CEBDA0B11D3C059900DBDBD0 /* MainViewController.xib */, + A1B2C3D4E5F6A7B8C9D0E1F2 /* ViewController.swift */, CEBDA0871D3C052600DBDBD0 /* CDVAppDelegate.h */, CEBDA0881D3C052600DBDBD0 /* CDVAppDelegate.m */, - 4F6D839819525B66003EBB16 /* AppDelegate.m */, + 4F6D839819525B66003EBB16 /* AppDelegate.swift */, 4F6D839919525B66003EBB16 /* AppDelegate.h */, 8272301A19D764160066A350 /* InitialViewController.h */, 8272301B19D764160066A350 /* InitialViewController.m */, @@ -1072,7 +1066,6 @@ B7168F6C1FACC29800A48DB5 /* LaunchScreen.storyboard in Resources */, B7BAD7621FBB7DEE0046629F /* IDPLoginViewController.xib in Resources */, 824A9DC11724CE4600C9BD79 /* config.xml in Resources */, - CEBDA0B31D3C059900DBDBD0 /* MainViewController.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1085,11 +1078,10 @@ files = ( 8272301C19D764160066A350 /* InitialViewController.m in Sources */, 82AF5AB71A0DAA8D006C7A4B /* CDVLogger.m in Sources */, - CEBDA0B21D3C059900DBDBD0 /* MainViewController.m in Sources */, + A1B2C3D4E5F6A7B8C9D0E1F3 /* ViewController.swift in Sources */, CEBDA0891D3C052600DBDBD0 /* CDVAppDelegate.m in Sources */, - 824A9BDE1721FCA400C9BD79 /* main.m in Sources */, 82638F0C19B8E1FD00FBB3C9 /* UIApplication+SalesforceHybridSDK.m in Sources */, - 4F6D839B19525B66003EBB16 /* AppDelegate.m in Sources */, + 4F6D839B19525B66003EBB16 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1199,6 +1191,8 @@ "$(PROJECT_DIR)/../../../external/cordova/CordovaLib/Classes/**", ); IPHONEOS_DEPLOYMENT_TARGET = 18.0; + SWIFT_VERSION = 5.0; + SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/../../../shared/hybrid/SampleApp-Bridging-Header.h"; LIBRARY_SEARCH_PATHS = ""; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ""; @@ -1253,6 +1247,8 @@ "$(PROJECT_DIR)/../../../external/cordova/CordovaLib/Classes/**", ); IPHONEOS_DEPLOYMENT_TARGET = 18.0; + SWIFT_VERSION = 5.0; + SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/../../../shared/hybrid/SampleApp-Bridging-Header.h"; LIBRARY_SEARCH_PATHS = ""; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; OTHER_LDFLAGS = ""; diff --git a/hybrid/SampleApps/AccountEditor/AccountEditor/main.m b/hybrid/SampleApps/AccountEditor/AccountEditor/main.m deleted file mode 100644 index 7006e38b..00000000 --- a/hybrid/SampleApps/AccountEditor/AccountEditor/main.m +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright (c) 2013-present, salesforce.com, inc. All rights reserved. - - Redistribution and use of this software in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this list of conditions - and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of - conditions and the following disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of salesforce.com, inc. nor the names of its contributors may be used to - endorse or promote products derived from this software without specific prior written - permission of salesforce.com, inc. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY - WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import - -int main(int argc, char *argv[]) -{ - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, @"AppDelegate"); - } -} diff --git a/hybrid/SampleApps/MobileSyncExplorerHybrid/MobileSyncExplorerHybrid.xcodeproj/project.pbxproj b/hybrid/SampleApps/MobileSyncExplorerHybrid/MobileSyncExplorerHybrid.xcodeproj/project.pbxproj index 280ae3e5..0a66b9bd 100644 --- a/hybrid/SampleApps/MobileSyncExplorerHybrid/MobileSyncExplorerHybrid.xcodeproj/project.pbxproj +++ b/hybrid/SampleApps/MobileSyncExplorerHybrid/MobileSyncExplorerHybrid.xcodeproj/project.pbxproj @@ -19,7 +19,7 @@ 4F6D68B3228E2ECF008C8A96 /* SalesforceHybridSDK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 829DA28C1C1264E40040F5F1 /* SalesforceHybridSDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 4F6D68B6228E2ECF008C8A96 /* Cordova.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEEF96DC1EB7CF050059CA79 /* Cordova.framework */; }; 4F6D68B7228E2ECF008C8A96 /* Cordova.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CEEF96DC1EB7CF050059CA79 /* Cordova.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 4F6D839B19525B66003EBB16 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4F6D839819525B66003EBB16 /* AppDelegate.m */; }; + 4F6D839B19525B66003EBB16 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F6D839819525B66003EBB16 /* AppDelegate.swift */; }; 4FC276B019DCBC6E008F4AA6 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 824A9DC01724CE4600C9BD79 /* config.xml */; }; 4FC276B119DCBC6E008F4AA6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 824A9BDA1721FCA400C9BD79 /* InfoPlist.strings */; }; 4FC276B219DCBC80008F4AA6 /* bootconfig.json in Copy Shared www Files */ = {isa = PBXBuildFile; fileRef = 4FC2768719DCBAD5008F4AA6 /* bootconfig.json */; }; @@ -55,7 +55,6 @@ 824A9BD21721FCA400C9BD79 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 824A9BD11721FCA400C9BD79 /* UIKit.framework */; }; 824A9BD41721FCA400C9BD79 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 824A9BD31721FCA400C9BD79 /* Foundation.framework */; }; 824A9BD61721FCA400C9BD79 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 824A9BD51721FCA400C9BD79 /* CoreGraphics.framework */; }; - 824A9BDE1721FCA400C9BD79 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 824A9BDD1721FCA400C9BD79 /* main.m */; }; 824A9DA91724C99800C9BD79 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 824A9DA81724C99800C9BD79 /* AudioToolbox.framework */; }; 824A9DAB1724C9C900C9BD79 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 824A9DAA1724C9C900C9BD79 /* AVFoundation.framework */; }; 824A9DAD1724C9D100C9BD79 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 824A9DAC1724C9D100C9BD79 /* CFNetwork.framework */; }; @@ -89,8 +88,7 @@ CE7BA1ED1D8CB355000B91D7 /* com.salesforce.plugin.network.js in Copy plugins Files */ = {isa = PBXBuildFile; fileRef = CE7BA1931D8CA3D5000B91D7 /* com.salesforce.plugin.network.js */; }; CE7BA1EE1D8CB355000B91D7 /* com.salesforce.util.push.js in Copy plugins Files */ = {isa = PBXBuildFile; fileRef = CE7BA1941D8CA3D5000B91D7 /* com.salesforce.util.push.js */; }; CEBDA0391D3C04A500DBDBD0 /* CDVAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBDA0381D3C04A500DBDBD0 /* CDVAppDelegate.m */; }; - CEBDA0BC1D3C05F500DBDBD0 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBDA0BA1D3C05F500DBDBD0 /* MainViewController.m */; }; - CEBDA0BD1D3C05F500DBDBD0 /* MainViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = CEBDA0BB1D3C05F500DBDBD0 /* MainViewController.xib */; }; + B2C3D4E5F6A7B8C9D0E1F2A4 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2C3D4E5F6A7B8C9D0E1F2A3 /* ViewController.swift */; }; CED747441E8C86C60019AA9D /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CED747431E8C86C60019AA9D /* WebKit.framework */; }; /* End PBXBuildFile section */ @@ -394,8 +392,8 @@ 4F5B96111DA8693E001627F2 /* force.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = force.js; sourceTree = ""; }; 4F5B96BE1DAD9ED8001627F2 /* com.salesforce.plugin.smartstore.client.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = com.salesforce.plugin.smartstore.client.js; sourceTree = ""; }; 4F5B96BF1DAD9ED8001627F2 /* com.salesforce.util.promiser.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = com.salesforce.util.promiser.js; sourceTree = ""; }; - 4F6D839819525B66003EBB16 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = ../../../../shared/hybrid/AppDelegate.m; sourceTree = ""; }; - 4F6D839919525B66003EBB16 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = ../../../../external/cordova/templates/project/__PROJECT_NAME__/AppDelegate.h; sourceTree = ""; }; + 4F6D839819525B66003EBB16 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = ../../../../shared/hybrid/AppDelegate.swift; sourceTree = ""; }; + 4F6D839919525B66003EBB16 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = ../../../../external/cordova/templates/project/App/AppDelegate.h; sourceTree = ""; }; 4FC2768519DCBAA3008F4AA6 /* com.salesforce.plugin.mobilesync.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = com.salesforce.plugin.mobilesync.js; sourceTree = ""; }; 4FC2768719DCBAD5008F4AA6 /* bootconfig.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = bootconfig.json; path = ../../../../external/shared/samples/mobilesyncexplorer/bootconfig.json; sourceTree = ""; }; 4FC2768819DCBAD5008F4AA6 /* MobileSyncExplorer.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = MobileSyncExplorer.html; path = ../../../../external/shared/samples/mobilesyncexplorer/MobileSyncExplorer.html; sourceTree = ""; }; @@ -430,7 +428,6 @@ 824A9BD51721FCA400C9BD79 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 824A9BD91721FCA400C9BD79 /* MobileSyncExplorerHybrid-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MobileSyncExplorerHybrid-Info.plist"; sourceTree = ""; }; 824A9BDB1721FCA400C9BD79 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 824A9BDD1721FCA400C9BD79 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ../../../../external/cordova/templates/project/__PROJECT_NAME__/main.m; sourceTree = ""; }; 824A9BDF1721FCA400C9BD79 /* MobileSyncExplorerHybrid-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MobileSyncExplorerHybrid-Prefix.pch"; sourceTree = ""; }; 824A9BF91721FE1100C9BD79 /* readme.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = readme.md; sourceTree = ""; }; 824A9DA41724C98900C9BD79 /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; }; @@ -476,9 +473,8 @@ CE7BA1941D8CA3D5000B91D7 /* com.salesforce.util.push.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = com.salesforce.util.push.js; sourceTree = ""; }; CEBDA0371D3C04A500DBDBD0 /* CDVAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVAppDelegate.h; path = ../../../../external/cordova/CordovaLib/include/Cordova/CDVAppDelegate.h; sourceTree = ""; }; CEBDA0381D3C04A500DBDBD0 /* CDVAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVAppDelegate.m; path = ../../../../external/cordova/CordovaLib/Classes/Public/CDVAppDelegate.m; sourceTree = ""; }; - CEBDA0B91D3C05F500DBDBD0 /* MainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MainViewController.h; path = ../../../../external/cordova/templates/project/__PROJECT_NAME__/MainViewController.h; sourceTree = ""; }; - CEBDA0BA1D3C05F500DBDBD0 /* MainViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MainViewController.m; path = ../../../../external/cordova/templates/project/__PROJECT_NAME__/MainViewController.m; sourceTree = ""; }; - CEBDA0BB1D3C05F500DBDBD0 /* MainViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = MainViewController.xib; path = ../../../../external/cordova/templates/project/__PROJECT_NAME__/MainViewController.xib; sourceTree = ""; }; + B2C3D4E5F6A7B8C9D0E1F2A3 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ViewController.swift; path = ../../../../external/cordova/templates/project/App/ViewController.swift; sourceTree = ""; }; + CEBDA0B91D3C05F500DBDBD0 /* MainViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MainViewController.h; path = ../../../../external/cordova/templates/project/App/MainViewController.h; sourceTree = ""; }; CED747431E8C86C60019AA9D /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; CEEF96D41EB7CF050059CA79 /* CordovaLib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CordovaLib.xcodeproj; path = ../../../external/cordova/CordovaLib/CordovaLib.xcodeproj; sourceTree = ""; }; /* End PBXFileReference section */ @@ -660,7 +656,6 @@ 824A9DC01724CE4600C9BD79 /* config.xml */, 824A9BD91721FCA400C9BD79 /* MobileSyncExplorerHybrid-Info.plist */, 824A9BDA1721FCA400C9BD79 /* InfoPlist.strings */, - 824A9BDD1721FCA400C9BD79 /* main.m */, 824A9BDF1721FCA400C9BD79 /* MobileSyncExplorerHybrid-Prefix.pch */, ); name = "Supporting Files"; @@ -696,11 +691,10 @@ children = ( B7BAD78B1FBB7EE40046629F /* IDPLoginViewController.xib */, CEBDA0B91D3C05F500DBDBD0 /* MainViewController.h */, - CEBDA0BA1D3C05F500DBDBD0 /* MainViewController.m */, - CEBDA0BB1D3C05F500DBDBD0 /* MainViewController.xib */, + B2C3D4E5F6A7B8C9D0E1F2A3 /* ViewController.swift */, CEBDA0371D3C04A500DBDBD0 /* CDVAppDelegate.h */, CEBDA0381D3C04A500DBDBD0 /* CDVAppDelegate.m */, - 4F6D839819525B66003EBB16 /* AppDelegate.m */, + 4F6D839819525B66003EBB16 /* AppDelegate.swift */, 4F6D839919525B66003EBB16 /* AppDelegate.h */, 8272301A19D764160066A350 /* InitialViewController.h */, 8272301B19D764160066A350 /* InitialViewController.m */, @@ -1080,7 +1074,6 @@ 4FC276B119DCBC6E008F4AA6 /* InfoPlist.strings in Resources */, B7168FB81FACC31100A48DB5 /* LaunchScreen.storyboard in Resources */, B7BAD78E1FBB7EE50046629F /* IDPLoginViewController.xib in Resources */, - CEBDA0BD1D3C05F500DBDBD0 /* MainViewController.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1093,11 +1086,10 @@ files = ( 8272301C19D764160066A350 /* InitialViewController.m in Sources */, 82AF5AE61A0DADA4006C7A4B /* CDVLogger.m in Sources */, - CEBDA0BC1D3C05F500DBDBD0 /* MainViewController.m in Sources */, + B2C3D4E5F6A7B8C9D0E1F2A4 /* ViewController.swift in Sources */, CEBDA0391D3C04A500DBDBD0 /* CDVAppDelegate.m in Sources */, - 824A9BDE1721FCA400C9BD79 /* main.m in Sources */, 82638F0C19B8E1FD00FBB3C9 /* UIApplication+SalesforceHybridSDK.m in Sources */, - 4F6D839B19525B66003EBB16 /* AppDelegate.m in Sources */, + 4F6D839B19525B66003EBB16 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1207,6 +1199,8 @@ "$(PROJECT_DIR)/../../../external/cordova/CordovaLib/Classes/**", ); IPHONEOS_DEPLOYMENT_TARGET = 18.0; + SWIFT_VERSION = 5.0; + SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/../../../shared/hybrid/SampleApp-Bridging-Header.h"; LIBRARY_SEARCH_PATHS = ""; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ""; @@ -1261,6 +1255,8 @@ "$(PROJECT_DIR)/../../../external/cordova/CordovaLib/Classes/**", ); IPHONEOS_DEPLOYMENT_TARGET = 18.0; + SWIFT_VERSION = 5.0; + SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/../../../shared/hybrid/SampleApp-Bridging-Header.h"; LIBRARY_SEARCH_PATHS = ""; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; OTHER_LDFLAGS = ""; diff --git a/hybrid/SampleApps/MobileSyncExplorerHybrid/MobileSyncExplorerHybrid/main.m b/hybrid/SampleApps/MobileSyncExplorerHybrid/MobileSyncExplorerHybrid/main.m deleted file mode 100644 index 7006e38b..00000000 --- a/hybrid/SampleApps/MobileSyncExplorerHybrid/MobileSyncExplorerHybrid/main.m +++ /dev/null @@ -1,32 +0,0 @@ -/* - Copyright (c) 2013-present, salesforce.com, inc. All rights reserved. - - Redistribution and use of this software in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this list of conditions - and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of - conditions and the following disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of salesforce.com, inc. nor the names of its contributors may be used to - endorse or promote products derived from this software without specific prior written - permission of salesforce.com, inc. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY - WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import - -int main(int argc, char *argv[]) -{ - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, @"AppDelegate"); - } -} diff --git a/libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/SFHybridViewController.m b/libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/SFHybridViewController.m index 6cc29949..bd6127a2 100644 --- a/libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/SFHybridViewController.m +++ b/libs/SalesforceHybridSDK/SalesforceHybridSDK/Classes/SFHybridViewController.m @@ -39,6 +39,7 @@ #import #import #import +#import #import #import #import diff --git a/shared/hybrid/AppDelegate.m b/shared/hybrid/AppDelegate.m deleted file mode 100644 index 4384a572..00000000 --- a/shared/hybrid/AppDelegate.m +++ /dev/null @@ -1,149 +0,0 @@ -/* - Copyright (c) 2023-present, salesforce.com, inc. All rights reserved. - - Redistribution and use of this software in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this list of conditions - and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of - conditions and the following disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of salesforce.com, inc. nor the names of its contributors may be used to - endorse or promote products derived from this software without specific prior written - permission of salesforce.com, inc. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY - WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "AppDelegate.h" -#import -#import "UIApplication+SalesforceHybridSDK.h" -#import "InitialViewController.h" -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -@implementation AppDelegate - -- (instancetype)init -{ - self = [super init]; - - // Need to use SalesforceHybridSDKManager in hybrid apps - [SalesforceHybridSDKManager initializeSDK]; - -#ifdef DEBUG - [SalesforceHybridSDKManager sharedManager].isDevSupportEnabled = YES; -#else - [SalesforceHybridSDKManager sharedManager].isDevSupportEnabled = NO; -#endif - - //App Setup for any changes to the current authenticated user - __weak __typeof (self) weakSelf = self; - [SFSDKAuthHelper registerBlockForCurrentUserChangeNotifications:^{ - __strong __typeof (weakSelf) strongSelf = weakSelf; - [strongSelf resetViewState:^{ - [strongSelf setupRootViewController]; - }]; - }]; - - //Uncomment following block to enable IDP Login flow. - /* - //scheme of idpAppp - [SalesforceHybridSDKManager sharedManager].idpAppURIScheme = @"sampleidpapp"; - //user friendly display name - [SalesforceHybridSDKManager sharedManager].appDisplayName = @"SampleAppOne"; - */ - - return self; -} - -#pragma mark - App event lifecycle - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - int cacheSizeMemory = 8 * 1024 * 1024; // 8MB - int cacheSizeDisk = 32 * 1024 * 1024; // 32MB - NSURLCache* sharedCache = [[SFLocalhostSubstitutionCache alloc] initWithMemoryCapacity:cacheSizeMemory diskCapacity:cacheSizeDisk diskPath:@"nsurlcache"]; - [NSURLCache setSharedURLCache:sharedCache]; - - self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - self.window.autoresizesSubviews = YES; - - [self initializeAppViewState]; - __weak __typeof (self) weakSelf = self; - - [SFSDKAuthHelper loginIfRequired:^{ - [weakSelf setupRootViewController]; - }]; - - return YES; // we don't want to run's Cordova didFinishLaunchingWithOptions - it creates another window with a webview - // if devs want to customize their AppDelegate.m, then they should get rid of AppDelegate+SalesforceHybrid.m - // and bring all of its code in their AppDelegate.m -} - -- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken -{ - [[SFPushNotificationManager sharedInstance] didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; - if ([SFUserAccountManager sharedInstance].currentUser.credentials.accessToken != nil) { - [[SFPushNotificationManager sharedInstance] registerSalesforceNotificationsWithCompletionBlock:nil failBlock:nil]; - } - [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; -} - -- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options -{ - - // Uncomment following block to enable IDP Login flow - // return [[SFUserAccountManager sharedInstance] handleIDPAuthenticationResponse:url options:options]; - return NO; - -} - -#pragma mark - Private methods - -- (void)initializeAppViewState -{ - if (![NSThread isMainThread]) { - dispatch_async(dispatch_get_main_queue(), ^{ - [self initializeAppViewState]; - }); - return; - } - - self.window.rootViewController = [[InitialViewController alloc] initWithNibName:nil bundle:nil]; - [self.window makeKeyAndVisible]; -} - -- (void)setupRootViewController -{ - self.viewController = [[SFHybridViewController alloc] initWithConfig:(SFHybridViewConfig*)[SalesforceHybridSDKManager sharedManager].appConfig]; - self.window.rootViewController = self.viewController; -} - -- (void)resetViewState:(void (^)(void))postResetBlock -{ - if ([self.window.rootViewController presentedViewController]) { - [self.window.rootViewController dismissViewControllerAnimated:NO completion:^{ - postResetBlock(); - }]; - } else { - postResetBlock(); - } -} - -@end diff --git a/shared/hybrid/AppDelegate.swift b/shared/hybrid/AppDelegate.swift new file mode 100644 index 00000000..12f0f6b7 --- /dev/null +++ b/shared/hybrid/AppDelegate.swift @@ -0,0 +1,114 @@ +/* + Copyright (c) 2026-present, salesforce.com, inc. All rights reserved. + + Redistribution and use of this software in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this list of conditions + and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of salesforce.com, inc. nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written + permission of salesforce.com, inc. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ + +import UIKit +import SalesforceHybridSDK +import SalesforceSDKCore + +@main +#if compiler(>=6.1) +@objc @implementation +#else +@_objcImplementation +#endif +extension AppDelegate { + + public override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Initialize SalesforceHybridSDKManager — required for hybrid apps + SalesforceHybridSDKManager.initializeSDK() + + #if DEBUG + SalesforceHybridSDKManager.shared.isDevSupportEnabled = true + #else + SalesforceHybridSDKManager.shared.isDevSupportEnabled = false + #endif + + // Set up URL cache with localhost substitution support for local hybrid apps + let cacheSizeMemory: UInt = 8 * 1024 * 1024 // 8 MB + let cacheSizeDisk: UInt = 32 * 1024 * 1024 // 32 MB + let sharedCache = SFLocalhostSubstitutionCache(memoryCapacity: cacheSizeMemory, diskCapacity: cacheSizeDisk, diskPath: "nsurlcache") + URLCache.shared = sharedCache + + window = UIWindow(frame: UIScreen.main.bounds) + window?.autoresizesSubviews = true + + initializeAppViewState() + + AuthHelper.loginIfRequired { [weak self] in + self?.setupRootViewController() + } + + // Register for user-change notifications so view state is reset on account switch + AuthHelper.registerBlock(forCurrentUserChangeNotifications: { [weak self] in + self?.resetViewState { + self?.setupRootViewController() + } + }) + + // Return false: Cordova's super implementation would create a second window + // with a bare WebView. We handle window setup entirely here. + return false + } + + public override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { + PushNotificationManager.sharedInstance().didRegisterForRemoteNotifications(withDeviceToken: deviceToken) + if UserAccountManager.shared.currentUserAccount?.credentials.accessToken != nil { + PushNotificationManager.sharedInstance().registerSalesforceNotifications(completionBlock: nil, failBlock: nil) + } + super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken) + } + + public override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { + // Uncomment to enable IDP Login flow: + // return UserAccountManager.shared.handleIDPAuthenticationResponse(url, options: options) + return false + } + + // MARK: - Private helpers + + private func initializeAppViewState() { + guard Thread.isMainThread else { + DispatchQueue.main.async { self.initializeAppViewState() } + return + } + // InitialViewController is an ObjC class — imported via Bridging-Header.h + // by the postinstall-ios.js hook which adds #import "InitialViewController.h" + window?.rootViewController = InitialViewController(nibName: nil, bundle: nil) + window?.makeKeyAndVisible() + } + + private func setupRootViewController() { + let config = SalesforceHybridSDKManager.shared.bootConfig as? SFHybridViewConfig + viewController = SFHybridViewController(config: config) + window?.rootViewController = viewController + } + + private func resetViewState(_ postResetBlock: @escaping () -> Void) { + if window?.rootViewController?.presentedViewController != nil { + window?.rootViewController?.dismiss(animated: false, completion: postResetBlock) + } else { + postResetBlock() + } + } +} diff --git a/shared/hybrid/SampleApp-Bridging-Header.h b/shared/hybrid/SampleApp-Bridging-Header.h new file mode 100644 index 00000000..8d29011f --- /dev/null +++ b/shared/hybrid/SampleApp-Bridging-Header.h @@ -0,0 +1,15 @@ +/* + Copyright (c) 2025-present, salesforce.com, inc. All rights reserved. + + Bridging header for hybrid sample apps. Provides ObjC visibility for + Cordova and Salesforce SDK classes used by AppDelegate.swift and ViewController.swift. + */ + +#import + +#define __CORDOVA_SILENCE_HEADER_DEPRECATIONS +#import "AppDelegate.h" +#import "MainViewController.h" +#undef __CORDOVA_SILENCE_HEADER_DEPRECATIONS + +#import "InitialViewController.h"