Instance configuration system for customizing Capacitor behavior, webview settings, and runtime options.
Primary configuration class for defining Capacitor instance behavior, webview properties, and runtime settings.
/**
* Configuration descriptor for Capacitor instances
*/
@objc(CAPInstanceDescriptor)
public class InstanceDescriptor: NSObject {
// MARK: - Initialization
/**
* Initialize with default configuration from application bundle
*/
public init()
/**
* Initialize with custom locations for app and configuration files
* @param appURL Location of the web app folder
* @param configURL Location of Capacitor configuration file (optional)
* @param cordovaURL Location of Cordova configuration file (optional)
*/
public init(at appURL: URL, configuration configURL: URL?, cordovaConfiguration cordovaURL: URL?)
// MARK: - App Location & Startup
/** Base file URL from which Capacitor loads resources (default: public/ in bundle) */
public var appLocation: URL!
/** Path relative to appLocation for initial page (default: index.html) */
public var appStartPath: String?
/** Error page path for displaying errors */
public var errorPath: String?
// MARK: - Server Configuration
/** Complete server URL override (overrides scheme/hostname if set) */
public var serverURL: String?
/** URL scheme for server URL (default: "capacitor") */
public var urlScheme: String?
/** Hostname for server URL (default: "localhost") */
public var urlHostname: String?
// MARK: - User Agent Customization
/** String to append to User-Agent (ignored if overridenUserAgentString is set) */
public var appendedUserAgentString: String?
/** Complete User-Agent string replacement (overrides appendedUserAgentString) */
public var overridenUserAgentString: String?
// MARK: - WebView Appearance
/** Background color for areas not covered by web content */
public var backgroundColor: UIColor?
/** Preferred content mode for the webview */
public var preferredContentMode: String?
// MARK: - WebView Behavior
/** Whether webview can scroll (corresponds to WKWebView.isScrollEnabled) */
public var scrollingEnabled: Bool
/** Whether webview supports zooming */
public var zoomingEnabled: Bool
/** Whether webview shows link previews (corresponds to WKWebView.allowsLinkPreview) */
public var allowLinkPreviews: Bool
/** Whether webview has initial focus */
public var hasInitialFocus: Bool
/** Content inset adjustment behavior (corresponds to UIScrollView.contentInsetAdjustmentBehavior) */
public var contentInsetAdjustmentBehavior: UIScrollViewContentInsetAdjustmentBehavior
// MARK: - Security & Navigation
/** Hostnames allowed for navigation without opening external browser */
public var allowedNavigationHostnames: [String]!
/** Whether to limit navigation to WKAppBoundDomains in Info.plist */
public var limitsNavigationsToAppBoundDomains: Bool
// MARK: - Development & Debugging
/** Enable web debugging (WKWebView.isInspectable on iOS 16.4+) */
public var isWebDebuggable: Bool
/** Logging behavior configuration */
public var loggingBehavior: InstanceLoggingBehavior
// MARK: - Plugin Configuration
/** Dictionary containing plugin-specific configuration */
public var pluginConfigurations: NSDictionary!
// MARK: - Notification Handling
/** Whether Capacitor should set itself as UNUserNotificationCenter delegate */
public var handleApplicationNotifications: Bool
// MARK: - Cordova Compatibility
/** Cordova configuration parser */
public var cordovaConfiguration: CDVConfigParser!
// MARK: - Metadata
/** Warnings generated during initialization */
public var warnings: InstanceWarning
/** Type of instance configuration */
public var instanceType: InstanceType { get }
/** Legacy configuration dictionary (deprecated) */
public var legacyConfig: NSDictionary!
}Usage Examples:
// Basic configuration
override func instanceDescriptor() -> InstanceDescriptor {
let descriptor = InstanceDescriptor()
descriptor.appLocation = Bundle.main.url(forResource: "www", withExtension: nil)!
return descriptor
}
// Advanced configuration
override func instanceDescriptor() -> InstanceDescriptor {
let descriptor = InstanceDescriptor()
// App setup
descriptor.appLocation = Bundle.main.url(forResource: "dist", withExtension: nil)!
descriptor.appStartPath = "main.html"
descriptor.serverURL = "https://myapp.example.com"
// Appearance
descriptor.backgroundColor = UIColor.systemBackground
descriptor.preferredContentMode = "mobile"
// WebView behavior
descriptor.scrollingEnabled = true
descriptor.zoomingEnabled = false
descriptor.allowLinkPreviews = true
// Security
descriptor.allowedNavigationHostnames = ["myapp.example.com", "api.myapp.com"]
descriptor.limitsNavigationsToAppBoundDomains = true
// Development
descriptor.isWebDebuggable = true
descriptor.loggingBehavior = [.debug, .production]
// User agent
descriptor.appendedUserAgentString = " MyApp/1.0"
return descriptor
}
// Custom file locations
let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let appURL = documentsPath.appendingPathComponent("webapp")
let configURL = Bundle.main.url(forResource: "capacitor.config", withExtension: "json")
let descriptor = InstanceDescriptor(
at: appURL,
configuration: configURL,
cordovaConfiguration: nil
)Runtime configuration object derived from InstanceDescriptor, used by the bridge during execution.
/**
* Processed runtime configuration derived from InstanceDescriptor
* All properties are readonly as configuration is processed during initialization
*/
@interface CAPInstanceConfiguration : NSObject
// MARK: - App Configuration
@property (nonatomic, readonly, nonnull) NSURL *appLocation;
@property (nonatomic, readonly, nullable) NSString *appStartPath;
@property (nonatomic, readonly, nullable) NSString *serverURL;
// MARK: - WebView Configuration
@property (nonatomic, readonly, nullable) UIColor *backgroundColor;
@property (nonatomic, readonly) BOOL scrollingEnabled;
@property (nonatomic, readonly) BOOL zoomingEnabled;
// MARK: - Security Configuration
@property (nonatomic, readonly, nonnull) NSArray<NSString*> *allowedNavigationHostnames;
// MARK: - Plugin Configuration
@property (nonatomic, readonly, nonnull) NSDictionary *pluginConfigurations;
// MARK: - Development Configuration
@property (nonatomic, readonly) CAPInstanceLoggingBehavior loggingBehavior;
@endUsage in Plugins:
class MyPlugin: CAPPlugin {
@objc func getConfiguration(_ call: CAPPluginCall) {
guard let config = bridge?.config else {
call.reject("Bridge not available")
return
}
let result: [String: Any] = [
"appLocation": config.appLocation.absoluteString,
"scrollingEnabled": config.scrollingEnabled,
"zoomingEnabled": config.zoomingEnabled,
"backgroundColor": config.backgroundColor?.description ?? "default"
]
call.resolve(["configuration": result])
}
}Type definitions for configuration flags and behavior options.
/**
* Instance type enumeration
*/
public enum InstanceType: Int {
/** Standard fixed configuration */
case fixed
/** Dynamic configuration that can change */
case variable
}
/**
* Instance warning flags for configuration validation
*/
public struct InstanceWarning: OptionSet {
public let rawValue: UInt
/** App directory not found */
public static let missingAppDir = InstanceWarning(rawValue: 1 << 0)
/** Configuration file missing */
public static let missingFile = InstanceWarning(rawValue: 1 << 1)
/** Configuration file invalid */
public static let invalidFile = InstanceWarning(rawValue: 1 << 2)
/** Cordova configuration file missing */
public static let missingCordovaFile = InstanceWarning(rawValue: 1 << 3)
/** Cordova configuration file invalid */
public static let invalidCordovaFile = InstanceWarning(rawValue: 1 << 4)
}
/**
* Logging behavior configuration options
*/
public struct InstanceLoggingBehavior: OptionSet {
public let rawValue: UInt
/** No logging */
public static let none = InstanceLoggingBehavior(rawValue: 1 << 0)
/** Debug logging enabled */
public static let debug = InstanceLoggingBehavior(rawValue: 1 << 1)
/** Production logging enabled */
public static let production = InstanceLoggingBehavior(rawValue: 1 << 2)
}Usage Examples:
// Check for configuration warnings
let descriptor = InstanceDescriptor()
if descriptor.warnings.contains(.missingAppDir) {
print("Warning: App directory not found")
}
// Configure logging
descriptor.loggingBehavior = [.debug, .production]
// Check instance type
switch descriptor.instanceType {
case .fixed:
print("Fixed configuration")
case .variable:
print("Variable configuration")
}Access plugin-specific configuration through the PluginConfig utility class.
/**
* Plugin-specific configuration access
*/
@objc(CAPPluginConfig)
public class PluginConfig: NSObject {
/**
* Get string configuration value
* @param key Configuration key
* @returns String value or nil
*/
public func getString(_ key: String) -> String?
/**
* Get string configuration value with default
* @param key Configuration key
* @param defaultValue Default value if key not found
* @returns String value or default
*/
public func getString(_ key: String, _ defaultValue: String) -> String
/**
* Get boolean configuration value
* @param key Configuration key
* @returns Boolean value or false if not found
*/
public func getBoolean(_ key: String) -> Bool
/**
* Get boolean configuration value with default
* @param key Configuration key
* @param defaultValue Default value if key not found
* @returns Boolean value or default
*/
public func getBoolean(_ key: String, _ defaultValue: Bool) -> Bool
/**
* Get integer configuration value
* @param key Configuration key
* @returns Integer value or 0 if not found
*/
public func getInt(_ key: String) -> Int
/**
* Get integer configuration value with default
* @param key Configuration key
* @param defaultValue Default value if key not found
* @returns Integer value or default
*/
public func getInt(_ key: String, _ defaultValue: Int) -> Int
/**
* Get object configuration value
* @param key Configuration key
* @returns Dictionary object or nil
*/
public func getObject(_ key: String) -> JSObject?
/**
* Get array configuration value
* @param key Configuration key
* @returns Array object or nil
*/
public func getArray(_ key: String) -> JSArray?
}Plugin Configuration Usage:
class MyPlugin: CAPPlugin {
override func load() {
super.load()
let config = getConfig()
// Get configuration values
let apiKey = config.getString("apiKey", "default-key")
let enabled = config.getBoolean("enabled", true)
let timeout = config.getInt("timeout", 30)
let servers = config.getArray("servers") ?? []
// Configure plugin with values
setupPlugin(apiKey: apiKey, enabled: enabled, timeout: timeout, servers: servers)
}
}