Skip to content

Commit fbc20d8

Browse files
committed
update for linnker test and podspec
1 parent 4ab878c commit fbc20d8

9 files changed

Lines changed: 205 additions & 142 deletions

File tree

ReactNativeNavigation.podspec

Lines changed: 6 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,8 @@
11
require 'json'
22

33
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4-
54
fabric_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == '1'
65

7-
# Detect if this is a Swift project by checking common iOS project locations
8-
# Avoid recursive directory scanning which can be slow in CI with large node_modules
9-
start_dir = File.expand_path('../../', __dir__)
10-
swift_delegate_path = nil
11-
12-
# Check specific, known locations where AppDelegate.swift typically exists
13-
# This avoids slow recursive directory traversal
14-
['ios', 'example/ios', 'playground/ios', 'app/ios', 'demo/ios'].each do |ios_dir|
15-
ios_path = File.join(start_dir, ios_dir)
16-
next unless Dir.exist?(ios_path)
17-
18-
# Check direct subdirectories (common project structures)
19-
# Most projects have: ios/ProjectName/AppDelegate.swift
20-
Dir.entries(ios_path).each do |entry|
21-
next if entry.start_with?('.') || entry == 'Pods' || entry == 'build' || entry == 'DerivedData'
22-
entry_path = File.join(ios_path, entry)
23-
next unless Dir.exist?(entry_path)
24-
25-
app_delegate_path = File.join(entry_path, 'AppDelegate.swift')
26-
if File.exist?(app_delegate_path)
27-
swift_delegate_path = app_delegate_path
28-
break
29-
end
30-
end
31-
break if swift_delegate_path
32-
end
33-
34-
swift_project = swift_delegate_path && File.exist?(swift_delegate_path)
35-
36-
if swift_project
37-
puts "ReactNativeNavigation: Swift AppDelegate detected - enabling Swift-compatible configuration"
38-
else
39-
puts "ReactNativeNavigation: Objective-C AppDelegate detected - using standard configuration"
40-
end
41-
426
Pod::Spec.new do |s|
437
s.name = "ReactNativeNavigation"
448
s.prepare_command = 'node autolink/postlink/__helpers__/generate_version_header.js'
@@ -58,13 +22,10 @@ Pod::Spec.new do |s|
5822
s.source_files = 'ios/**/*.{h,m,mm,cpp}'
5923
s.exclude_files = "ios/ReactNativeNavigationTests/**/*.*", "ios/OCMock/**/*.*"
6024

61-
# Only expose headers for Swift projects
62-
if swift_project
63-
s.public_header_files = [
64-
'ios/RNNAppDelegate.h',
65-
'ios/ReactNativeVersionExtracted.h'
66-
]
67-
end
25+
s.public_header_files = [
26+
'ios/RNNAppDelegate.h',
27+
'ios/ReactNativeVersionExtracted.h'
28+
]
6829
end
6930

7031
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32 -DFOLLY_CFG_NO_COROUTINES=1'
@@ -76,11 +37,8 @@ Pod::Spec.new do |s|
7637
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
7738
}
7839

79-
# Only add DEFINES_MODULE for Swift projects
80-
if swift_project
81-
xcconfig_settings["DEFINES_MODULE"] = "YES"
82-
end
83-
40+
xcconfig_settings["DEFINES_MODULE"] = "YES"
41+
8442
s.pod_target_xcconfig = xcconfig_settings
8543

8644
if fabric_enabled
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`appDelegateLinker should work for RN 0.77 & 0.78 with Objective-C 1`] = `
4+
"#import "AppDelegate.h"
5+
#import <ReactNativeNavigation/ReactNativeNavigation.h>
6+
7+
#import <React/RCTBundleURLProvider.h>
8+
9+
@implementation AppDelegate
10+
11+
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
12+
{
13+
14+
return [super application:application didFinishLaunchingWithOptions:launchOptions];
15+
}
16+
17+
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
18+
{
19+
#if DEBUG
20+
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
21+
#else
22+
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
23+
#endif
24+
}
25+
26+
/// This method controls whether the \`concurrentRoot\`feature of React18 is turned on or off.
27+
///
28+
/// @see: https://reactjs.org/blog/2022/03/29/react-v18.html
29+
/// @note: This requires to be rendering on Fabric (i.e. on the New Architecture).
30+
/// @return: \`true\` if the \`concurrentRoot\` feature is enabled. Otherwise, it returns \`false\`.
31+
- (BOOL)concurrentRootEnabled
32+
{
33+
return true;
34+
}
35+
36+
@end "
37+
`;
38+
39+
exports[`appDelegateLinker should work for RN 0.77 & 0.78 with Swift 1`] = `
40+
"import UIKit
41+
import React
42+
import ReactNativeNavigation
43+
import ReactAppDependencyProvider
44+
45+
@main
46+
class AppDelegate: RNNAppDelegate {
47+
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
48+
self.moduleName = "app"
49+
self.dependencyProvider = RCTAppDependencyProvider()
50+
51+
// You can add your custom initial props in the dictionary below.
52+
// They will be passed down to the ViewController used by React Native.
53+
self.initialProps = [:]
54+
55+
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
56+
}
57+
58+
override func sourceURL(for bridge: RCTBridge) -> URL? {
59+
self.bundleURL()
60+
}
61+
62+
override func bundleURL() -> URL? {
63+
#if DEBUG
64+
RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
65+
#else
66+
Bundle.main.url(forResource: "main", withExtension: "jsbundle")
67+
#endif
68+
}
69+
} "
70+
`;
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`appDelegateLinker should work with Swift bridgeless RN 0.79 1`] = `
4+
"import UIKit
5+
import React
6+
import ReactNativeNavigation
7+
import ReactAppDependencyProvider
8+
9+
@main
10+
class AppDelegate: RNNAppDelegate {
11+
12+
override func application(
13+
_ application: UIApplication,
14+
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
15+
) -> Bool {
16+
self.reactNativeDelegate = ReactNativeDelegate()
17+
super.application(application, didFinishLaunchingWithOptions: launchOptions)
18+
19+
20+
21+
return true
22+
}
23+
}
24+
25+
class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate {
26+
override func sourceURL(for bridge: RCTBridge) -> URL? {
27+
self.bundleURL()
28+
}
29+
30+
override func bundleURL() -> URL? {
31+
#if DEBUG
32+
RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
33+
#else
34+
Bundle.main.url(forResource: "main", withExtension: "jsbundle")
35+
#endif
36+
}
37+
}"
38+
`;
39+

autolink/postlink/appDelegateLinker.test.js

Lines changed: 0 additions & 89 deletions
This file was deleted.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import fs from 'node:fs';
2+
import * as mockHelpers from './__helpers__/fixtures';
3+
4+
jest.mock('./log');
5+
6+
const { getReactNativeVersion } = require('./__helpers__/reactNativeVersion');
7+
const rnVersion = getReactNativeVersion();
8+
const shouldSkip = rnVersion && rnVersion.minor >= 79;
9+
10+
// Conditionally skip entire test suite based on RN version
11+
(shouldSkip ? describe.skip : describe)('appDelegateLinker', () => {
12+
it('should work for RN 0.77 & 0.78 with Objective-C', () => {
13+
jest.mock('./path', () => {
14+
const appDelegatePath = mockHelpers.prepareFixtureDuplicate77({
15+
userFixtureFileName: 'AppDelegate.mm.template',
16+
patchedFixtureFileName: 'rnn-tests_AppDelegate.mm',
17+
});
18+
return {
19+
appDelegate: appDelegatePath,
20+
};
21+
});
22+
23+
const AppDelegateLinker = require('./appDelegateLinker');
24+
const linker = new AppDelegateLinker();
25+
26+
linker.link();
27+
const appDelegateContent = fs.readFileSync(linker.appDelegatePath, 'utf8');
28+
expect(appDelegateContent).toMatchSnapshot();
29+
});
30+
31+
it('should work for RN 0.77 & 0.78 with Swift', () => {
32+
jest.mock('./path', () => {
33+
const tmpAppDelegatePath = mockHelpers.prepareFixtureDuplicate77({
34+
userFixtureFileName: 'AppDelegate.swift.template',
35+
patchedFixtureFileName: 'rnn-tests_AppDelegate.swift',
36+
});
37+
38+
return {
39+
appDelegate: tmpAppDelegatePath,
40+
};
41+
});
42+
43+
const AppDelegateLinker = require('./appDelegateLinker');
44+
const linker = new AppDelegateLinker();
45+
linker.link();
46+
47+
const appDelegateContent = fs.readFileSync(linker.appDelegatePath, 'utf8');
48+
expect(appDelegateContent).toMatchSnapshot();
49+
});
50+
});
51+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import fs from 'node:fs';
2+
import * as mockHelpers from './__helpers__/fixtures';
3+
4+
jest.mock('./log');
5+
6+
const { getReactNativeVersion } = require('./__helpers__/reactNativeVersion');
7+
const rnVersion = getReactNativeVersion();
8+
const shouldSkip = !rnVersion || rnVersion.minor < 79;
9+
10+
// Conditionally skip entire test suite based on RN version
11+
(shouldSkip ? describe.skip : describe)('appDelegateLinker', () => {
12+
it('should work with Swift bridgeless RN 0.79', () => {
13+
jest.mock('./path', () => {
14+
const tmpAppDelegatePath = mockHelpers.prepareFixtureDuplicate79({
15+
userFixtureFileName: 'AppDelegate.swift.template',
16+
patchedFixtureFileName: 'rnn-tests_AppDelegate79.swift',
17+
});
18+
19+
return {
20+
appDelegate: tmpAppDelegatePath,
21+
};
22+
});
23+
24+
const AppDelegateLinker = require('./appDelegateLinker');
25+
const linker = new AppDelegateLinker();
26+
linker.link();
27+
28+
const appDelegateContent = fs.readFileSync(linker.appDelegatePath, 'utf8');
29+
expect(appDelegateContent).toMatchSnapshot();
30+
});
31+
});
32+

ios/ReactNativeNavigation.xcodeproj/project.pbxproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,9 @@
238238
507ACB1223F44D1E00829911 /* RNNComponentView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 507ACB1023F44D1E00829911 /* RNNComponentView.mm */; };
239239
507ACB1523F44E5200829911 /* RNNComponentRootView.h in Headers */ = {isa = PBXBuildFile; fileRef = 507ACB1323F44E5200829911 /* RNNComponentRootView.h */; };
240240
507ACB1623F44E5200829911 /* RNNComponentRootView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 507ACB1423F44E5200829911 /* RNNComponentRootView.mm */; };
241-
507DBBDB2A31DE8400F1FC74 /* RNNAppDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 507DBBD92A31DE8400F1FC74 /* RNNAppDelegate.h */; };
241+
507DBBDB2A31DE8400F1FC74 /* RNNAppDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 507DBBD92A31DE8400F1FC74 /* RNNAppDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
242242
507DBBDC2A31DE8400F1FC74 /* RNNAppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 507DBBDA2A31DE8400F1FC74 /* RNNAppDelegate.mm */; };
243+
507DBBDD2A31DE8400F1FC75 /* ReactNativeVersionExtracted.h in Headers */ = {isa = PBXBuildFile; fileRef = 507DBBDE2A31DE8400F1FC76 /* ReactNativeVersionExtracted.h */; settings = {ATTRIBUTES = (Public, ); }; };
243244
507E7D57201DDD3000444E6C /* RNNSharedElementAnimationOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 507E7D55201DDD3000444E6C /* RNNSharedElementAnimationOptions.h */; };
244245
507E7D58201DDD3000444E6C /* RNNSharedElementAnimationOptions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 507E7D56201DDD3000444E6C /* RNNSharedElementAnimationOptions.mm */; };
245246
507F43C51FF4F17C00D9425B /* RNNTopTabsViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 507F43C31FF4F17C00D9425B /* RNNTopTabsViewController.h */; };
@@ -735,6 +736,7 @@
735736
507ACB1423F44E5200829911 /* RNNComponentRootView.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNComponentRootView.mm; sourceTree = "<group>"; };
736737
507DBBD92A31DE8400F1FC74 /* RNNAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNAppDelegate.h; sourceTree = "<group>"; };
737738
507DBBDA2A31DE8400F1FC74 /* RNNAppDelegate.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = RNNAppDelegate.mm; sourceTree = "<group>"; };
739+
507DBBDE2A31DE8400F1FC76 /* ReactNativeVersionExtracted.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReactNativeVersionExtracted.h; sourceTree = "<group>"; };
738740
507E7D55201DDD3000444E6C /* RNNSharedElementAnimationOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNSharedElementAnimationOptions.h; sourceTree = "<group>"; };
739741
507E7D56201DDD3000444E6C /* RNNSharedElementAnimationOptions.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNNSharedElementAnimationOptions.mm; sourceTree = "<group>"; };
740742
507F43C31FF4F17C00D9425B /* RNNTopTabsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNNTopTabsViewController.h; sourceTree = "<group>"; };
@@ -1588,6 +1590,7 @@
15881590
7BA500741E2544B9001B9E1B /* ReactNativeNavigation.mm */,
15891591
507DBBD92A31DE8400F1FC74 /* RNNAppDelegate.h */,
15901592
507DBBDA2A31DE8400F1FC74 /* RNNAppDelegate.mm */,
1593+
507DBBDE2A31DE8400F1FC76 /* ReactNativeVersionExtracted.h */,
15911594
5030B62023D5B4CA008F1642 /* Color+Interpolation.h */,
15921595
5030B61F23D5B4CA008F1642 /* Color+Interpolation.mm */,
15931596
5030B62623D5B54D008F1642 /* LNInterpolable.h */,
@@ -1857,6 +1860,7 @@
18571860
5050465421F8F4490035497A /* RNNReactComponentRegistry.h in Headers */,
18581861
506BF65C2600AE4200A22755 /* CenterTransition.h in Headers */,
18591862
507DBBDB2A31DE8400F1FC74 /* RNNAppDelegate.h in Headers */,
1863+
507DBBDD2A31DE8400F1FC75 /* ReactNativeVersionExtracted.h in Headers */,
18601864
504AFE741FFFF0540076E904 /* RNNTopTabsOptions.h in Headers */,
18611865
50E38DD723A7A2BE009817F6 /* AnimatedViewFactory.h in Headers */,
18621866
E8E5182E1F83A48B000467AC /* RNNTransitionStateHolder.h in Headers */,

0 commit comments

Comments
 (0)