16

The official React Native documentation to run app on iOS device using offline bundle says

Open ios/YourApp/AppDelegate.m

Uncomment the line, jsCodeLocation = [[NSBundle mainBundle] ...

Using latest react-native 0.30.0, this line is no longer present in the default AppDelegate.m file. Excerpt from the default AppDelegate.m file

NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];

RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                    moduleName:@"TestAppDelete"
                                             initialProperties:nil
                                                 launchOptions:launchOptions];

If I try to use the jsCodeLocation as it used to be in previous versions, it is returned as null

jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];

I am not sure why is the URL for main.jsbundle returned as null. Is it not created by the packager anymore. If it should be created using the latest version also, how can I confirm it?

If you have run a react-native 0.30.0 app on an iOS device using offline bundle, please share the instructions to do so.

6 Answers 6

27

EDIT: The whole bundle ip detection should be automatic on the latest release of react-native. If you select your device on xcode do build and run and run the app once. It should save an offline bundle on the phone so that if it doesn't find a packager server running, it will use the offline bundle.

source: https://github.com/facebook/react-native/commit/8c29a52c54392ce52148e7d3aa9f835537453aa4


If you change to a release scheme while building your app, that will compile your app with the offline bundle.

Product > Scheme > Edit Scheme > set build configuration to Release.

Not sure why they didn't update the documentation for the Appdelegate.m method. Looks like the line is still there on the sources. [Edit: there's a pull request for this]

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks a lot for the reply. This change was not mentioned in the release notes and since I have changed the AppDelegate file in my app, I just replaced it after react-native upgrade and the documentation wasn't updated either which confused things further. Just a note - If I run the app on the device without changing the Build Configuration to Release, then I was able to run the app as long it was connected to the mac. If I stop the app, disconnect the phone and try to run it again, it doesn't start. Setting the Build Configuration to Release helped in that case. Thanks again!
I hope I could upvote the answer multiple times :). I just spent too much time yesterday to figure it out.
Once changing to release version I am no longer able to debug my app using the react native debugger.. Also the build time takes ages. Is this the only solution to this? Can I somehow solve this and keep running in debug mode? Thanks
Changing to a Release configuration solves only half the problem. Release builds don't allow debugging, which kind of leaves us flying blind.
@EdoftheMountain We fixed it without changing the scheme to a release version, check out what we did here stackoverflow.com/a/40730709/1438478
|
13

When I open the global proxy in ShadowsocksX, automatic IP detection won't return http://localhost:8081/index.ios.bundle in the debug mode. That's why the URL for main.jsbundle returned as null.

How to solve?

Option 1:

replace

jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];

with

jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"];

This method could disable automatic IP detection.

Option 2:

Switch your proxy mode if you open the global proxy mode.

1 Comment

Option 1 doesn't work anymore with latest react-native
3

tl;dr Make sure your localhost ip address is explicitly stated in your hosts file, and that your hosts file hasn't become corrupted.

So our team kept hitting this issue. It turns out that React Native reads the host file on your machine looking for the URL to store, so that it can pull the js to create an offline bundle, or to just reach the packager while the app is running on your device.

We actually weren't trying to run this as an offline bundle, just in the ios simulator, so we were left really scratching our heads. We found the fix because the needed fix was also causing other issues with react native. Our etc/hosts file on a mac didn't have the localhost ip explicitly stated. I added that in and the problem seemed to go away. Forgive me as I don't know much about osx and dns resolution but it seems that with the new automatic ip detection, this is now necessary.

I am not sure how react native is getting the ip, if it is reading the hosts file, or the host file is propogating something else in osx that rn is reading, but if the above fix doesnt work for you, I would look to see if the hosts file itself is corrupted with certain characters that cause it not to be read. In my hunting for the solution to this problem, I came across many posts and questions about malformed hosts files that caused issues with localhost being resolved properly.

Also, it seems there is an effort underway to update the ip detection, but I am not well versed enough in obj c to know if this issue would be corrected by the new code. Maybe someone can take a look? https://github.com/facebook/react-native/pull/8789

Another also, clearing your osx DNS cache may help https://coolestguidesontheplanet.com/clear-the-local-dns-cache-in-osx/

1 Comment

+1 .. Awesome research! I only had this issue with certain routers. (I move around a lot). But the line for pointing in hosts had been commented out. Putting 127.0.0.1 localhost into my hosts file fixed the problem! Thank you so much! I was searching for hours for a fix.
2

For me the problem was that I had fiddled with the Info.plist and removed the localhost app transport security exception. Adding this back into Info.plist fixed it for me:

<key>NSAppTransportSecurity</key>
<!--See http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/ -->
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>localhost</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
</dict>

Comments

2

The only fix I could get to work on react native 0.37 was to go back to the "old school" method of manually editing jsCodeLocation in AppDelegate.m. Debugging is good again!

Be sure your device and development machine are on the same wi-fi, and maybe disconnect any wired Ethernet until you get it working.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  NSURL *jsCodeLocation;

  // Comment-out, cannot get past error: bundleURL must be non-nil when not implementing loadSourceForBridge
  //jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];

#if DEBUG
  NSLog(@"AppDelegate:DEBUG");

#if TARGET_IPHONE_SIMULATOR
  NSLog(@"AppDelegate:DEBUG:TARGET_IPHONE_SIMULATOR");
  jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle"];
#else
  NSLog(@"AppDelegate:DEBUG:!TARGET_IPHONE_SIMULATOR");
  NSLog(@"To device debug, open RCTWebSocketExecutor.m & replace localhost with MacBook IP.");
  // Get dev host IP Address:
  //    ifconfig | grep inet\ | tail -1 | cut -d " " -f 2
  jsCodeLocation = [NSURL URLWithString:@"http://192.16.29.213:8081/index.ios.bundle"];
#endif

#else
  NSLog(@"AppDelegate:RELEASE jsbundle");
  jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif

  NSLog(@"jsCodeLocation = %@",jsCodeLocation);


  RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                      moduleName:@"BluetoothConnect"
                                               initialProperties:nil
                                                   launchOptions:launchOptions];
  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  return YES;
}

Comments

0

First I would make sure I have ios-deploy installed.

You can do so by running npm install -g ios-deploy

Then connect the iphone you want the app to be installed in into your mac.

Then run

react-native run-ios --device "ABC’s iPhone" --configuration=release

This would create a offline js bundled app and install it onto the iphone.

PS: If it errors out saying

Signing for "<app name>" requires a development team. 
Select a development team in the project editor.

Then open up the project inside ios/ in Xcode and Select the target -> General Tab Under signing choose the signing team and choose automatically manage signing.

Then save and re-run the command.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.