janziemba
janziemba

Reputation: 462

Use iOS launch screen as app background in react-native

I can't figure out how to use iOS launch screen as background for my app. On Android, it's on background by default and you just need to make your React root view's background transparent to show it.

This is how my AppDelegate.m looks like now: https://github.com/facebook/react-native/blob/master/local-cli/templates/HelloWorld/ios/HelloWorld/AppDelegate.m

I have tried this solution by Peter Minarik: https://peterminarik.tumblr.com/post/153039209421/how-to-fix-the-initial-white-flash-in-your-react ...but it makes my app crash on startup. There is no error and the only thing I can find in simulator's log is:

com.apple.CoreSimulator.SimDevice.4D60253D-C11F-4927-A3A3-3CC555432326[53234] (com.apple.videosubscriptionsd[20497]): Service exited with abnormal code: 1

Peter's solution:

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  // ...

  // 1. Load the LaunchScreen from the xib file
  UIView *backgroundView = [[[NSBundle mainBundle] loadNibNamed:@"LaunchScreen" owner:self options:nil] firstObject];

  RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation ... ];

  // 2. Set the backgroundColor of the react view to be transparent
  rootView.backgroundColor = [UIColor clearColor];

  // ...

  // 3. Set the backgroundView as main view for the rootViewController (instead of the rootView)
  rootViewController.view = backgroundView;

  [self.window makeKeyAndVisible];

  // 4. After the window is visible, add the rootView as a subview to your backgroundView
  [backgroundView addSubview:rootView];

  // 5. Then make the rootViews frame the same as the backgroundView
  rootView.frame = backgroundView.frame;

  return YES;
}

@end

This is my LaunchScreen.xib:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES">
    <device id="retina4_7" orientation="portrait">
        <adaptation id="fullscreen"/>
    </device>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <objects>
        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
        <viewController id="CQd-0M-zUa">
            <layoutGuides>
                <viewControllerLayoutGuide type="top" id="JTh-uz-DhT"/>
                <viewControllerLayoutGuide type="bottom" id="Pi7-cH-HiC"/>
            </layoutGuides>
            <view key="view" contentMode="scaleToFill" id="kTS-qs-i9x">
                <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                <subviews>
                    <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="Image" translatesAutoresizingMaskIntoConstraints="NO" id="f0g-jh-Eny">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                    </imageView>
                    <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" fixedFrame="YES" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="S0g-wl-Fc0">
                        <rect key="frame" x="79" y="306" width="240" height="128"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                        <mutableString key="text">Lorem ipsum dolor sit...</mutableString>
                        <fontDescription key="fontDescription" type="system" pointSize="14"/>
                        <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
                    </textView>
                </subviews>
                <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
            </view>
            <point key="canvasLocation" x="1327.5" y="531.5"/>
        </viewController>
    </objects>
    <resources>
        <image name="Image" width="375" height="667"/>
    </resources>
</document>

I don't know Objective-C. Could you please help me?

Upvotes: 0

Views: 1239

Answers (1)

janziemba
janziemba

Reputation: 462

I have figured out how to do it. The reason the previous solution didn't work was that my LaunchScreen contains a View Controller, not a View. So you don't have to create a new instance of UIViewController, just use this one and attach rootView as a subview.

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

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

  UIViewController *rootViewController = [[[NSBundle mainBundle] loadNibNamed:@"LaunchScreen" owner:self options:nil] firstObject];

  rootView.backgroundColor = [UIColor clearColor];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  self.window.rootViewController = rootViewController;

  [self.window makeKeyAndVisible];

  [rootViewController.view addSubview:rootView];

  rootView.frame = rootViewController.view.frame;

  return YES;

Now my launch screen is always in the background of the app.

Upvotes: 2

Related Questions