inject method
Injects custom deep linking logic into AppDelegate.swift. Returns the modified Swift code. Idempotent.
Implementation
String inject(String content) {
if (content.contains('custom_deeplink') || content.contains('methodChannel')) {
// Already injected/configured
return content;
}
var modified = content;
// 1. Inject state variables after the class declaration
final classRegex = RegExp(r'class\s+AppDelegate\s*:[^{]*\{');
final classMatch = classRegex.firstMatch(modified);
if (classMatch == null) {
throw CodeInjectionException('Could not locate class AppDelegate declaration in AppDelegate.swift');
}
final stateVars = '''
private var initialLink: String?
private var methodChannel: FlutterMethodChannel?
''';
modified = modified.substring(0, classMatch.end) + stateVars + modified.substring(classMatch.end);
// 2. Inject MethodChannel initialization in didFinishLaunchingWithOptions
final launchRegex = RegExp(
r'func\s+application\(\s*_\s+application:\s*UIApplication,\s*didFinishLaunchingWithOptions[^)]*\)\s*->\s*Bool\s*\{'
);
final launchMatch = launchRegex.firstMatch(modified);
if (launchMatch == null) {
throw CodeInjectionException('Could not locate didFinishLaunchingWithOptions method in AppDelegate.swift');
}
final methodChannelSetup = '''
if let controller = window?.rootViewController as? FlutterViewController {
methodChannel = FlutterMethodChannel(name: "custom_deeplink", binaryMessenger: controller.binaryMessenger)
methodChannel?.setMethodCallHandler({ [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) in
if call.method == "getInitialLink" {
result(self?.initialLink)
self?.initialLink = nil
} else {
result(FlutterMethodNotImplemented)
}
})
}
''';
modified = modified.substring(0, launchMatch.end) + methodChannelSetup + modified.substring(launchMatch.end);
// 3. Inject application(_:open:options:) and application(_:continue:restorationHandler:)
final openUrlAndUserActivityMethods = '''
override func application(
_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey : Any] = [:]
) -> Bool {
initialLink = url.absoluteString
methodChannel?.invokeMethod("onLink", arguments: initialLink)
return super.application(app, open: url, options: options)
}
override func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
if let url = userActivity.webpageURL {
initialLink = url.absoluteString
methodChannel?.invokeMethod("onLink", arguments: initialLink)
}
}
return super.application(application, continue: userActivity, restorationHandler: restorationHandler)
}
''';
final lastBraceIndex = modified.lastIndexOf('}');
if (lastBraceIndex == -1) {
throw CodeInjectionException('AppDelegate.swift is missing a closing brace.');
}
modified = modified.substring(0, lastBraceIndex) + openUrlAndUserActivityMethods + modified.substring(lastBraceIndex);
return modified;
}