Skip to content

Commit 8679c0b

Browse files
committed
[ReactNative] Add deep linking api
1 parent f53510a commit 8679c0b

20 files changed

Lines changed: 646 additions & 121 deletions

File tree

Examples/2048/2048/AppDelegate.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ @implementation AppDelegate
1616
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
1717
{
1818
NSURL *jsCodeLocation;
19-
RCTRootView *rootView = [[RCTRootView alloc] init];
2019

2120
// Loading JavaScript code - uncomment the one you want.
2221

@@ -37,8 +36,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
3736
// and uncomment the next following line
3837
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
3938

40-
rootView.scriptURL = jsCodeLocation;
41-
rootView.moduleName = @"Game2048";
39+
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
40+
moduleName:@"Game2048"
41+
launchOptions:launchOptions];
4242

4343
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
4444
UIViewController *rootViewController = [[UIViewController alloc] init];

Examples/Movies/Movies.xcodeproj/project.pbxproj

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
1414
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
1515
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
16+
140D9B661AC36C42004F25EE /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14312D241AC3654D00CDC950 /* libRCTLinking.a */; };
1617
58C5726B1AA6239E00CDF9C8 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58C5725B1AA6236500CDF9C8 /* libRCTText.a */; };
1718
58C5726C1AA623A200CDF9C8 /* libReactKit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58C572681AA6236600CDF9C8 /* libReactKit.a */; };
1819
/* End PBXBuildFile section */
@@ -32,6 +33,13 @@
3233
remoteGlobalIDString = 58B5115D1A9E6B3D00147676;
3334
remoteInfo = RCTImage;
3435
};
36+
14312D231AC3654D00CDC950 /* PBXContainerItemProxy */ = {
37+
isa = PBXContainerItemProxy;
38+
containerPortal = 14312D1E1AC3654D00CDC950 /* RCTLinking.xcodeproj */;
39+
proxyType = 2;
40+
remoteGlobalIDString = 134814201AA4EA6300B7C361;
41+
remoteInfo = RCTLinking;
42+
};
3543
58C5725A1AA6236500CDF9C8 /* PBXContainerItemProxy */ = {
3644
isa = PBXContainerItemProxy;
3745
containerPortal = 587650F61A9EB120008B8F17 /* RCTText.xcodeproj */;
@@ -58,6 +66,7 @@
5866
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Movies/Images.xcassets; sourceTree = "<group>"; };
5967
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Movies/Info.plist; sourceTree = "<group>"; };
6068
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Movies/main.m; sourceTree = "<group>"; };
69+
14312D1E1AC3654D00CDC950 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = ../../Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = "<group>"; };
6170
587650F61A9EB120008B8F17 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../../Libraries/Text/RCTText.xcodeproj; sourceTree = SOURCE_ROOT; };
6271
587650F91A9EB120008B8F17 /* ReactKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ReactKit.xcodeproj; path = ../../ReactKit/ReactKit.xcodeproj; sourceTree = SOURCE_ROOT; };
6372
/* End PBXFileReference section */
@@ -67,6 +76,7 @@
6776
isa = PBXFrameworksBuildPhase;
6877
buildActionMask = 2147483647;
6978
files = (
79+
140D9B661AC36C42004F25EE /* libRCTLinking.a in Frameworks */,
7080
1341801E1AA91750003F314A /* libRCTNetwork.a in Frameworks */,
7181
13442C061AA90EA00037E5B0 /* libRCTImage.a in Frameworks */,
7282
58C5726B1AA6239E00CDF9C8 /* libRCTText.a in Frameworks */,
@@ -106,9 +116,18 @@
106116
name = Movies;
107117
sourceTree = "<group>";
108118
};
119+
14312D1F1AC3654D00CDC950 /* Products */ = {
120+
isa = PBXGroup;
121+
children = (
122+
14312D241AC3654D00CDC950 /* libRCTLinking.a */,
123+
);
124+
name = Products;
125+
sourceTree = "<group>";
126+
};
109127
58C571FC1AA6124500CDF9C8 /* Libraries */ = {
110128
isa = PBXGroup;
111129
children = (
130+
14312D1E1AC3654D00CDC950 /* RCTLinking.xcodeproj */,
112131
134180151AA91740003F314A /* RCTNetwork.xcodeproj */,
113132
13442C001AA90E7D0037E5B0 /* RCTImage.xcodeproj */,
114133
587650F61A9EB120008B8F17 /* RCTText.xcodeproj */,
@@ -195,6 +214,10 @@
195214
ProductGroup = 13442C011AA90E7D0037E5B0 /* Products */;
196215
ProjectRef = 13442C001AA90E7D0037E5B0 /* RCTImage.xcodeproj */;
197216
},
217+
{
218+
ProductGroup = 14312D1F1AC3654D00CDC950 /* Products */;
219+
ProjectRef = 14312D1E1AC3654D00CDC950 /* RCTLinking.xcodeproj */;
220+
},
198221
{
199222
ProductGroup = 134180161AA91740003F314A /* Products */;
200223
ProjectRef = 134180151AA91740003F314A /* RCTNetwork.xcodeproj */;
@@ -230,6 +253,13 @@
230253
remoteRef = 13442C041AA90E7D0037E5B0 /* PBXContainerItemProxy */;
231254
sourceTree = BUILT_PRODUCTS_DIR;
232255
};
256+
14312D241AC3654D00CDC950 /* libRCTLinking.a */ = {
257+
isa = PBXReferenceProxy;
258+
fileType = archive.ar;
259+
path = libRCTLinking.a;
260+
remoteRef = 14312D231AC3654D00CDC950 /* PBXContainerItemProxy */;
261+
sourceTree = BUILT_PRODUCTS_DIR;
262+
};
233263
58C5725B1AA6236500CDF9C8 /* libRCTText.a */ = {
234264
isa = PBXReferenceProxy;
235265
fileType = archive.ar;
@@ -294,12 +324,10 @@
294324
);
295325
INFOPLIST_FILE = "$(SRCROOT)/Movies/Info.plist";
296326
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
297-
LIBRARY_SEARCH_PATHS = (
298-
"$(inherited)",
299-
"/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/Libraries/Network/build/Debug-iphoneos",
300-
);
327+
LIBRARY_SEARCH_PATHS = "$(inherited)";
301328
OTHER_LDFLAGS = "-ObjC";
302329
PRODUCT_NAME = Movies;
330+
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../Libraries/**";
303331
};
304332
name = Debug;
305333
};
@@ -314,12 +342,10 @@
314342
);
315343
INFOPLIST_FILE = "$(SRCROOT)/Movies/Info.plist";
316344
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
317-
LIBRARY_SEARCH_PATHS = (
318-
"$(inherited)",
319-
"/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/Libraries/Network/build/Debug-iphoneos",
320-
);
345+
LIBRARY_SEARCH_PATHS = "$(inherited)";
321346
OTHER_LDFLAGS = "-ObjC";
322347
PRODUCT_NAME = Movies;
348+
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../Libraries/**";
323349
};
324350
name = Release;
325351
};

Examples/Movies/Movies/AppDelegate.m

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99

1010
#import "AppDelegate.h"
1111

12+
#import "RCTLinkingManager.h"
1213
#import "RCTRootView.h"
1314

1415
@implementation AppDelegate
1516

1617
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
1718
{
1819
NSURL *jsCodeLocation;
19-
RCTRootView *rootView = [[RCTRootView alloc] init];
2020

2121
// Loading JavaScript code - uncomment the one you want.
2222

@@ -37,8 +37,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
3737
// and uncomment the next following line
3838
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
3939

40-
rootView.scriptURL = jsCodeLocation;
41-
rootView.moduleName = @"MoviesApp";
40+
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
41+
moduleName:@"MoviesApp"
42+
launchOptions:launchOptions];
4243

4344
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
4445
UIViewController *rootViewController = [[UIViewController alloc] init];
@@ -48,4 +49,15 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
4849
return YES;
4950
}
5051

52+
- (BOOL)application:(UIApplication *)application
53+
openURL:(NSURL *)url
54+
sourceApplication:(NSString *)sourceApplication
55+
annotation:(id)annotation
56+
{
57+
return [RCTLinkingManager application:application
58+
openURL:url
59+
sourceApplication:sourceApplication
60+
annotation:annotation];
61+
}
62+
5163
@end

Examples/Movies/Movies/Info.plist

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,17 @@
1818
<string>1.0</string>
1919
<key>CFBundleSignature</key>
2020
<string>????</string>
21+
<key>CFBundleURLTypes</key>
22+
<array>
23+
<dict>
24+
<key>CFBundleTypeRole</key>
25+
<string>Editor</string>
26+
<key>CFBundleURLSchemes</key>
27+
<array>
28+
<string>movies</string>
29+
</array>
30+
</dict>
31+
</array>
2132
<key>CFBundleVersion</key>
2233
<string>1</string>
2334
<key>LSRequiresIPhoneOS</key>
@@ -28,13 +39,13 @@
2839
<array>
2940
<string>armv7</string>
3041
</array>
31-
<key>UIViewControllerBasedStatusBarAppearance</key>
32-
<false/>
3342
<key>UISupportedInterfaceOrientations</key>
3443
<array>
3544
<string>UIInterfaceOrientationPortrait</string>
3645
<string>UIInterfaceOrientationLandscapeLeft</string>
3746
<string>UIInterfaceOrientationLandscapeRight</string>
3847
</array>
48+
<key>UIViewControllerBasedStatusBarAppearance</key>
49+
<false/>
3950
</dict>
4051
</plist>

Examples/SampleApp/iOS/AppDelegate.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ @implementation AppDelegate
1616
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
1717
{
1818
NSURL *jsCodeLocation;
19-
RCTRootView *rootView = [[RCTRootView alloc] init];
2019

2120
// Loading JavaScript code - uncomment the one you want.
2221

@@ -37,8 +36,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
3736
// and uncomment the next following line
3837
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
3938

40-
rootView.scriptURL = jsCodeLocation;
41-
rootView.moduleName = @"SampleApp";
39+
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
40+
moduleName:@"SampleApp"
41+
launchOptions:launchOptions];
4242

4343
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
4444
UIViewController *rootViewController = [[UIViewController alloc] init];

Examples/TicTacToe/TicTacToe/AppDelegate.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ @implementation AppDelegate
1616
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
1717
{
1818
NSURL *jsCodeLocation;
19-
RCTRootView *rootView = [[RCTRootView alloc] init];
2019

2120
// Loading JavaScript code - uncomment the one you want.
2221

@@ -37,8 +36,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
3736
// and uncomment the next following line
3837
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
3938

40-
rootView.scriptURL = jsCodeLocation;
41-
rootView.moduleName = @"TicTacToeApp";
39+
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
40+
moduleName:@"TicTacToeApp"
41+
launchOptions:launchOptions];
4242

4343
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
4444
UIViewController *rootViewController = [[UIViewController alloc] init];

Examples/UIExplorer/UIExplorer/AppDelegate.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ @implementation AppDelegate
1616
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
1717
{
1818
NSURL *jsCodeLocation;
19-
RCTRootView *rootView = [[RCTRootView alloc] init];
2019

2120
// Loading JavaScript code - uncomment the one you want.
2221

@@ -37,8 +36,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
3736
// and uncomment the next following line
3837
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
3938

40-
rootView.scriptURL = jsCodeLocation;
41-
rootView.moduleName = @"UIExplorerApp";
39+
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
40+
moduleName:@"UIExplorerApp"
41+
launchOptions:launchOptions];
4242

4343
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
4444
UIViewController *rootViewController = [[UIViewController alloc] init];

IntegrationTests/AppDelegate.m

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ @implementation AppDelegate
1616
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
1717
{
1818
NSURL *jsCodeLocation;
19-
RCTRootView *rootView = [[RCTRootView alloc] init];
2019

2120
// Loading JavaScript code - uncomment the one you want.
2221

@@ -37,8 +36,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
3736
// and uncomment the next following line
3837
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
3938

40-
rootView.scriptURL = jsCodeLocation;
41-
rootView.moduleName = @"IntegrationTestsApp";
39+
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
40+
moduleName:@"IntegrationTestsApp"
41+
launchOptions:launchOptions];
4242

4343
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
4444
UIViewController *rootViewController = [[UIViewController alloc] init];

Libraries/LinkingIOS/LinkingIOS.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*
9+
* @providesModule LinkingIOS
10+
* @flow
11+
*/
12+
'use strict';
13+
14+
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
15+
var RCTLinkingManager = require('NativeModules').LinkingManager;
16+
var invariant = require('invariant');
17+
18+
var _notifHandlers = {};
19+
var _initialURL = RCTLinkingManager &&
20+
RCTLinkingManager.initialURL;
21+
22+
var DEVICE_NOTIF_EVENT = 'openURL';
23+
24+
class LinkingIOS {
25+
static addEventListener(type, handler) {
26+
invariant(
27+
type === 'url',
28+
'LinkingIOS only supports `url` events'
29+
);
30+
_notifHandlers[handler] = RCTDeviceEventEmitter.addListener(
31+
DEVICE_NOTIF_EVENT,
32+
(notifData) => {
33+
handler(new LinkingIOS(notifData));
34+
}
35+
);
36+
}
37+
38+
static removeEventListener(type, handler) {
39+
invariant(
40+
type === 'url',
41+
'LinkingIOS only supports `url` events'
42+
);
43+
if (!_notifHandlers[handler]) {
44+
return;
45+
}
46+
_notifHandlers[handler].remove();
47+
_notifHandlers[handler] = null;
48+
}
49+
50+
static openURL(url) {
51+
invariant(
52+
typeof url === 'string',
53+
'Invalid url: should be a string'
54+
);
55+
RCTLinkingManager.openURL(url);
56+
}
57+
58+
static canOpenURL(url, callback) {
59+
invariant(
60+
typeof url === 'string',
61+
'Invalid url: should be a string'
62+
);
63+
invariant(
64+
typeof callback === 'function',
65+
'A valid callback function is required'
66+
);
67+
RCTLinkingManager.canOpenURL(url, callback);
68+
}
69+
70+
static popInitialURL() {
71+
var initialURL = _initialURL;
72+
_initialURL = null;
73+
return initialURL;
74+
}
75+
}
76+
77+
module.exports = LinkingIOS;

0 commit comments

Comments
 (0)