Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions Example/e2etest/ios/AwesomeProject/AppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#import "RCTPushy.h"

#import <React/RCTBundleURLProvider.h>
#import <React/RCTLinkingManager.h>
#import <ReactAppDependencyProvider/RCTAppDependencyProvider.h>

@implementation AppDelegate
Expand All @@ -13,6 +14,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
// You can add your custom initial props in the dictionary below.
// They will be passed down to the ViewController used by React Native.
self.initialProps = @{};
// UIScene life cycle (required from the iOS 27 SDK on): the window belongs
// to the scene, so React Native starts in SceneDelegate, not here.
self.automaticallyLoadReactNativeWindow = NO;

return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
Expand All @@ -28,3 +32,58 @@ - (NSURL *)bundleURL
}

@end

// The scene owns the window: React Native starts here once it connects. A URL
// or universal link that launched the app arrives with the scene instead of
// in didFinishLaunching's launch options, so it is handed to React Native
// as a launch option (Linking.getInitialURL); later ones are forwarded to
// RCTLinkingManager (Linking 'url' events).
@interface SceneDelegate : UIResponder <UIWindowSceneDelegate>
@property (nonatomic, strong) UIWindow *window;
@end

@implementation SceneDelegate

- (void)scene:(UIScene *)scene
willConnectToSession:(UISceneSession *)session
options:(UISceneConnectionOptions *)connectionOptions
{
if (![scene isKindOfClass:[UIWindowScene class]]) {
return;
}
AppDelegate *app = (AppDelegate *)UIApplication.sharedApplication.delegate;
NSMutableDictionary *launchOptions = [NSMutableDictionary dictionary];
NSURL *url = connectionOptions.URLContexts.anyObject.URL;
if (url != nil) {
launchOptions[UIApplicationLaunchOptionsURLKey] = url;
}
NSUserActivity *activity = connectionOptions.userActivities.anyObject;
if (activity != nil) {
launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey] = @{
@"UIApplicationLaunchOptionsUserActivityKey" : activity,
UIApplicationLaunchOptionsUserActivityTypeKey : activity.activityType,
};
}
self.window = [[UIWindow alloc] initWithWindowScene:(UIWindowScene *)scene];
app.window = self.window;
[app.reactNativeFactory startReactNativeWithModuleName:app.moduleName
inWindow:self.window
initialProperties:app.initialProps
launchOptions:launchOptions];
}

- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts
{
for (UIOpenURLContext *context in URLContexts) {
[RCTLinkingManager application:UIApplication.sharedApplication openURL:context.URL options:@{}];
}
}

- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity
{
[RCTLinkingManager application:UIApplication.sharedApplication
continueUserActivity:userActivity
restorationHandler:^(NSArray<id<UIUserActivityRestoring>> *_Nullable objects) {}];
}

@end
17 changes: 17 additions & 0 deletions Example/e2etest/ios/AwesomeProject/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,23 @@
<string>For saving photos</string>
<key>RCTNewArchEnabled</key>
<true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default</string>
<key>UISceneDelegateClassName</key>
<string>SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
Expand Down
80 changes: 49 additions & 31 deletions Example/expoUsePushy/bun.lock

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions Example/expoUsePushy/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PODS:
- EXConstants (57.0.18):
- ExpoModulesCore
- Expo (57.0.22):
- Expo (57.0.30):
- ExpoModulesCore
- ExpoModulesJSI
- hermes-engine
Expand All @@ -27,7 +27,7 @@ PODS:
- ReactCommon/turbomodule/core
- ReactNativeDependencies
- Yoga
- ExpoAsset (57.0.17):
- ExpoAsset (57.0.20):
- ExpoModulesCore
- ExpoBlur (57.0.3):
- ExpoModulesCore
Expand All @@ -49,7 +49,7 @@ PODS:
- ExpoModulesCore
- ExpoLogBox (57.0.4):
- React-Core
- ExpoModulesCore (57.0.18):
- ExpoModulesCore (57.0.23):
- ExpoModulesJSI
- hermes-engine
- RCTRequired
Expand All @@ -73,13 +73,13 @@ PODS:
- ReactCommon/turbomodule/core
- ReactNativeDependencies
- Yoga
- ExpoModulesJSI (57.1.0):
- ExpoModulesJSI (57.1.2):
- React-Core
- ReactCommon
- ExpoModulesWorklets (57.0.18):
- ExpoModulesWorklets (57.0.23):
- ExpoModulesCore
- ExpoModulesJSI
- ExpoModulesWorkletsAdapter (57.0.18):
- ExpoModulesWorkletsAdapter (57.0.23):
- ExpoModulesCore
- ExpoModulesJSI
- ExpoModulesWorklets
Expand Down Expand Up @@ -2685,8 +2685,8 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
EXConstants: 8948a340eb14bf2bdaaa0e21a63cb9343860b87a
Expo: 70c70c1692c316b909fbe4996cf9c92b9cfb1bae
ExpoAsset: b3999ffb3d4049b6c870708c60ea2209ace9f170
Expo: 83ceec8498d39a83bfcdf6ad56118bc6c5c81c72
ExpoAsset: 2581425f9b581b4fce3c83ffc9f28528d1c4ee68
ExpoBlur: 975b78b65b3c8f475c44bd8f8b53948146b1ff9b
ExpoDomWebView: beaec034e51bd028428b98bb1f2633ab79c6d095
ExpoFileSystem: 28778f942725170102f7c6cf4dee05a526ddacd0
Expand All @@ -2697,10 +2697,10 @@ SPEC CHECKSUMS:
ExpoKeepAwake: 72af0b3be3615e59bc819d26061ff4e06b155ee0
ExpoLinking: 15c8ddb0eb4a778950712ea4a6feedf021778852
ExpoLogBox: 80957303325cd4439137765c90a87d7f22aaf2ff
ExpoModulesCore: 3326eab55538b7c14f454c9b8b14df6a6935585f
ExpoModulesJSI: 9df8e7c9719f59e8c001ec33611774137fc1484a
ExpoModulesWorklets: 986cf72c18400743869b4642d243115f831e404d
ExpoModulesWorkletsAdapter: 45b4ea99adb80abaa012b45e9a9543b4763275c9
ExpoModulesCore: 63590ddb7c82f80af35fe078a6ad54b6d0923e3c
ExpoModulesJSI: b767422763350d2b248fb218f71bbb286fd2ee77
ExpoModulesWorklets: 22d1898cfa60b815ffc7421c775e2e6a1bd8dc82
ExpoModulesWorkletsAdapter: 9d1e55ef8c1efc403c1cde5e716451f77ec05019
ExpoRouter: 8f978c2ecb68bfb1f2eeff765ba2ddd8d66c54e0
ExpoSplashScreen: e771da4f26d550ea4fd067d8fb942657e47bb846
ExpoSymbols: 37a3a6e5847edb08b83a5ee04d3b46525e205f00
Expand Down
15 changes: 6 additions & 9 deletions Example/expoUsePushy/ios/expoUsePushy/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ internal import Expo
import React
import ReactAppDependencyProvider

// UIScene life cycle (required from the iOS 27 SDK on): Expo's
// ExpoAppSceneDelegate (Info.plist UISceneDelegateClassName) creates the window
// for the connecting scene, starts the factory below in it, and forwards scene
// URL, user-activity, life-cycle and quick-action events to this delegate and
// its subscribers. ExpoReactNativeFactoryProvider is how it finds the factory.
@main
class AppDelegate: ExpoAppDelegate {
class AppDelegate: ExpoAppDelegate, ExpoReactNativeFactoryProvider {
var window: UIWindow?

var reactNativeDelegate: ExpoReactNativeFactoryDelegate?
Expand All @@ -20,14 +25,6 @@ class AppDelegate: ExpoAppDelegate {
reactNativeDelegate = delegate
reactNativeFactory = factory

#if os(iOS) || os(tvOS)
window = UIWindow(frame: UIScreen.main.bounds)
factory.startReactNative(
withModuleName: "main",
in: window,
launchOptions: launchOptions)
#endif

return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

Expand Down
17 changes: 17 additions & 0 deletions Example/expoUsePushy/ios/expoUsePushy/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,23 @@
<string>$(RCT_METRO_PORT)</string>
<key>RCTNewArchEnabled</key>
<true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default</string>
<key>UISceneDelegateClassName</key>
<string>EXExpoAppSceneDelegate</string>
</dict>
</array>
</dict>
</dict>
<key>UILaunchStoryboardName</key>
<string>SplashScreen</string>
<key>UIRequiredDeviceCapabilities</key>
Expand Down
2 changes: 1 addition & 1 deletion Example/expoUsePushy/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@react-navigation/bottom-tabs": "^7.3.10",
"@react-navigation/elements": "^2.3.8",
"@react-navigation/native": "^7.1.6",
"expo": "~57.0.22",
"expo": "~57.0.30",
"expo-blur": "~57.0.3",
"expo-constants": "~57.0.18",
"expo-font": "~57.0.4",
Expand Down
59 changes: 59 additions & 0 deletions Example/testHotUpdate/ios/AwesomeProject/AppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#import "RCTPushy.h"

#import <React/RCTBundleURLProvider.h>
#import <React/RCTLinkingManager.h>
#import <ReactAppDependencyProvider/RCTAppDependencyProvider.h>

@implementation AppDelegate
Expand All @@ -13,6 +14,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
// You can add your custom initial props in the dictionary below.
// They will be passed down to the ViewController used by React Native.
self.initialProps = @{};
// UIScene life cycle (required from the iOS 27 SDK on): the window belongs
// to the scene, so React Native starts in SceneDelegate, not here.
self.automaticallyLoadReactNativeWindow = NO;

return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
Expand All @@ -28,3 +32,58 @@ - (NSURL *)bundleURL
}

@end

// The scene owns the window: React Native starts here once it connects. A URL
// or universal link that launched the app arrives with the scene instead of
// in didFinishLaunching's launch options, so it is handed to React Native
// as a launch option (Linking.getInitialURL); later ones are forwarded to
// RCTLinkingManager (Linking 'url' events).
@interface SceneDelegate : UIResponder <UIWindowSceneDelegate>
@property (nonatomic, strong) UIWindow *window;
@end

@implementation SceneDelegate

- (void)scene:(UIScene *)scene
willConnectToSession:(UISceneSession *)session
options:(UISceneConnectionOptions *)connectionOptions
{
if (![scene isKindOfClass:[UIWindowScene class]]) {
return;
}
AppDelegate *app = (AppDelegate *)UIApplication.sharedApplication.delegate;
NSMutableDictionary *launchOptions = [NSMutableDictionary dictionary];
NSURL *url = connectionOptions.URLContexts.anyObject.URL;
if (url != nil) {
launchOptions[UIApplicationLaunchOptionsURLKey] = url;
}
NSUserActivity *activity = connectionOptions.userActivities.anyObject;
if (activity != nil) {
launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey] = @{
@"UIApplicationLaunchOptionsUserActivityKey" : activity,
UIApplicationLaunchOptionsUserActivityTypeKey : activity.activityType,
};
}
self.window = [[UIWindow alloc] initWithWindowScene:(UIWindowScene *)scene];
app.window = self.window;
[app.reactNativeFactory startReactNativeWithModuleName:app.moduleName
inWindow:self.window
initialProperties:app.initialProps
launchOptions:launchOptions];
}

- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts
{
for (UIOpenURLContext *context in URLContexts) {
[RCTLinkingManager application:UIApplication.sharedApplication openURL:context.URL options:@{}];
}
}

- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity
{
[RCTLinkingManager application:UIApplication.sharedApplication
continueUserActivity:userActivity
restorationHandler:^(NSArray<id<UIUserActivityRestoring>> *_Nullable objects) {}];
}

@end
17 changes: 17 additions & 0 deletions Example/testHotUpdate/ios/AwesomeProject/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,23 @@
<string>For saving photos</string>
<key>RCTNewArchEnabled</key>
<true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default</string>
<key>UISceneDelegateClassName</key>
<string>SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
Expand Down
Loading