react-navigation.github.io icon indicating copy to clipboard operation
react-navigation.github.io copied to clipboard

Add Swift AppDelegate setup instructions for deep linking

Open kleviss opened this issue 6 months ago • 3 comments

This PR adds an alternative setup option for iOS projects using Swift, introduced in React Native v0.79.0. The new section provides developers with the necessary AppDelegate.swift implementation for handling deep links.

It includes new Swift code snippets for configuring deep linking in the AppDelegate.swift file, enhancing the documentation for users implementing Universal Links in their React Native applications. The previous content has been slightly modified for clarity.

kleviss avatar May 14 '25 11:05 kleviss

Deploy Preview for react-navigation-docs ready!

Name Link
Latest commit 138bb7ec091510a70f9d79269d89486d731bea61
Latest deploy log https://app.netlify.com/projects/react-navigation-docs/deploys/68869a186f97e1000877720d
Deploy Preview https://deploy-preview-1428--react-navigation-docs.netlify.app
Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

netlify[bot] avatar May 14 '25 11:05 netlify[bot]

I think this is also related to https://github.com/react-navigation/react-navigation.github.io/issues/1425, but the changes I have made here have not created any build issues and are working perfectly fine. In my case I had set up the app with v6 before, and deep linking and everything was working, so all the configurations on XCode were done. The RN New Arch introduces AppDelegate.swift, so this was needed to be added there so it properly works.

kleviss avatar May 15 '25 09:05 kleviss

This is the complete AppDelegate.swift file for my case. Note that it also includes push notifications configurations, and my actual app bundle name is replaced with yourAppName.

import ReactAppDependencyProvider
import React_RCTAppDelegate
import UIKit
import UserNotifications

@main
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
  var window: UIWindow?

  var reactNativeDelegate: ReactNativeDelegate?
  var reactNativeFactory: RCTReactNativeFactory?

  func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
  ) -> Bool {
    let delegate = ReactNativeDelegate()
    let factory = RCTReactNativeFactory(delegate: delegate)
    delegate.dependencyProvider = RCTAppDependencyProvider()

    reactNativeDelegate = delegate
    reactNativeFactory = factory

    window = UIWindow(frame: UIScreen.main.bounds)

    factory.startReactNative(
      withModuleName: "yourAppName",
      in: window,
      launchOptions: launchOptions
    )

    UNUserNotificationCenter.current().delegate = self

    return true
  }

  // MARK: - Push Notification Delegate Methods

  func application(
    _ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
  ) {
    // Assuming RNCPushNotificationIOS has a static method or instance method available in Swift
    // You might need to check the specific library documentation for the correct Swift usage.
    // Example (syntax may vary based on RNCPushNotificationIOS Swift bridging):
    RNCPushNotificationIOS.didRegisterForRemoteNotifications(withDeviceToken: deviceToken)
  }

  func application(
    _ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError
  ) {
    // Example:
    RNCPushNotificationIOS.didFailToRegisterForRemoteNotificationsWithError(error)
  }

  func application(
    _ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
    fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
  ) {
    // Example:
    RNCPushNotificationIOS.didReceiveRemoteNotification(
      userInfo, fetchCompletionHandler: completionHandler)
  }

  // MARK: - UNUserNotificationCenterDelegate Methods

  func userNotificationCenter(
    _ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse,
    withCompletionHandler completionHandler: @escaping () -> Void
  ) {
    // Example:
    RNCPushNotificationIOS.didReceive(response)
    completionHandler()  // Call the completion handler
  }

  func userNotificationCenter(
    _ center: UNUserNotificationCenter, willPresent notification: UNNotification,
    withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
  ) {
    // Example:
    completionHandler([.sound, .list, .banner, .badge])  // Or the options you need
  }

  // MARK: - Deep Linking / URL Scheme Handling

  func application(
    _ application: UIApplication, open url: URL,
    options: [UIApplication.OpenURLOptionsKey: Any] = [:]
  ) -> Bool {
    return RCTLinkingManager.application(application, open: url, options: options)
  }

  // For Universal Links
  func application(
    _ application: UIApplication, continue userActivity: NSUserActivity,
    restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
  ) -> Bool {
    return RCTLinkingManager.application(
      application, continue: userActivity, restorationHandler: restorationHandler)
  }
}

class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate {
  override func sourceURL(for bridge: RCTBridge) -> URL? {
    self.bundleURL()
  }

  override func bundleURL() -> URL? {
    #if DEBUG
      RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
    #else
      Bundle.main.url(forResource: "main", withExtension: "jsbundle")
    #endif
  }
}

kleviss avatar May 15 '25 09:05 kleviss

We might want to rewrite this section using tabs

<Tabs groupId="app-delegate">
<TabItem value="objc" label="AppDelegate.m">
// ...
</TabItem>
<TabItem value="swift" label="AppDelegate.swift">
// ...
</TabItem>
</Tabs>


If your app is using [Universal Links](https://developer.apple.com/ios/universal-links/), you'll need to add the following code as well:

<Tabs groupId="app-delegate">
<TabItem value="objc" label="AppDelegate.m">
// ...
</TabItem>
<TabItem value="swift" label="AppDelegate.swift">
// ...
</TabItem>
</Tabs>

chetan-satpute avatar Jul 04 '25 12:07 chetan-satpute