25
votes

In order to get iPad Pro to use full resolution at launch, we have to use a Launch Screen File.

I've never used a Launch Screen XIB/Storyboard before, because my app is backwards compatible to iOS 7. Normally I use a LaunchImage asset catalog to define a specific static image for each device dimension and launch orientation.

Now I'm trying to define a Launch Screen File that acts like a LaunchImage asset catalog, but I'm struggling to do it. In particular:

1) I don't see a good way to select a different UIImage depending on the exact size of the device, e.g. show one image to iPhone 4S users and another image to iPhone 5 users.

2) I don't see a way to select a different UIImage for iPad Portrait and iPad Landscape views. Size classes seem to think that both iPad Portrait and iPad Landscape are "Regular" width and "Regular" height, so any UIImage that would show up on iPad Portrait will also show up in iPad Landscape.

5
From iOS 8 onwards the preferred way to support everything is with a Launch Screen, Size Classes and Auto Layout rather than provide static assets. Are you looking for help implementing a Launch Screen? There is a lot of documentation on this. If you need to continue supporting iOS 7 you will need to provide static assets for your supported devices, are you needing help supporting both iOS 7 and 8/9?Jessedc
@Jessedc It's surprisingly difficult to implement a Launch Screen that behaves exactly like a Launch Image, e.g. showing different static images for iPhone 4S vs. iPhone 5. Ordinarily, I wouldn't bother; if you want a Launch Image, just use a Launch Image, right? Why bother with a Launch Screen? Well, iPad Pro is the answer to that question. I HAVE to use a Launch Screen to get full resolution with iPad Pro. So now I'm trying to replicate the advantages of a Launch Image in the context of Launch Screen.Dan Fabulich
Just so I'm clear, you are saying your requirement is to display completely different Launch Screen content based on the device type and launch orientation? Additionally, your reference implementation is the behaviour exhibited by having Default.png images and naming them all accordingly (eg Default-Portrait@2x~ipad.png). Am I correct?Jessedc
@Jessedc Yup. (Technically I was using a "LaunchImage" asset catalog, but it's the same idea.) I've updated the question to include the clarification.Dan Fabulich
It seems like this may not be possible. I've posed another related question instead: Force iPad Pro to full resolution without Launch ScreenDan Fabulich

5 Answers

4
votes

The system loads the launch file before launching the app which creates some constraints on what it can contain (some of which may force you back to static image files):

1.The app is not yet loaded so the view hierarchy does not exist and the system can not call any custom view controller setup code you may have in the app (e.g. viewDidLoad)

2.You can only use standard UIKit classes so you can use UIView or UIViewController but not a custom subclass. If you try to set a custom class you will get an Illegal Configuration error in Xcode.

3.The launch file can only use basic UIKit views such as UIImageView and UILabel. You cannot use a UIWebView.

4.If you are using a storyboard you can specify multiple view controllers but there are again some limitations. For example you can embed view controllers in a navigation or tab bar controller but more complex container classes such as UISplitViewController do not work (at least not yet).

5.Localizing the launch file does not currently seem to have any effect. The base localization is always used so you will probably want to avoid text on the launch screen.

6.You cannot specify different launch files for iPad and iPhone. This may be a problem if you have significantly different interfaces for those devices as there is only so much you can do with auto layout and size classes.

Note that if you are deploying to iOS 7 you will still need to include the static launch image files. You can include both a launch image file and static launch images. Devices such as the iPhone 6 running iOS 8 will use the launch image file whilst iOS 7 devices will fallback to the launch images.

2
votes
  1. First create all your images. Then, open up your asset catalog and right click -> App Icons & Launch Images -> New iOS Launch Image. This will create an file to drag all your files into. Do that. Name the asset "Launch." enter image description here

  2. Create a new launch screen storyboard with command-n. Choose iOS -> User Interface -> Launch Screen. Call the file "Launch Screen."

  3. In your Launch Screen storyboard, select the view controller's view

[selecting the view.

  1. Find the UIImageView placeholder from the object library in the bottom corner of the right side ba, and drag it into the launch screen view.

UIImageView

  1. Now, select the image view in the storyboard, and type in the name of the image from your asset catalog.

enter image description here

  1. Control drag from the UIImageView to it's container view to set up auto layout constraints as follows :

enter image description here

  1. Optional... if you want it to look nice in your storyboard, select the view and do option-cmd-= to update the frame of the UIImageView.

  2. Go to your info.plist, and type the name of your storyboard ("Launch Screen") for the key "Launch screen interface file base name"

  3. Clean and run.

Hope that helps and that I didn't forget anything!

2
votes

You can use Size Classes to specify different images for different screen sizes, but this not help you handle cases of iPhone 4S and iPhone 5 screens

1
votes

A different approach is using spacer views that position the correct image in the visible area and move the other one off screen (see my original answer to a similar question here).

You can't provide different images for different screen sizes (iPhone 4, iPhone X, ...), but if you want different images for iPhone and iPad and different images for portrait and landscape this solution is for you.

I created an example project on github if you want to try it out. It works on iPad and iPhone.

Constraints in Interface Builder

The important constraints are

PortraitSpacer.width ≤ 5 × view.width
PortraitSpacer.width ≤ 5 × view.height

LandscapeSpacer.width ≥ 5 × view.width
LandscapeSpacer.width ≥ 5 × view.height

PositionSpacer.width = 5 × view.width

where view.width and view.height are the main view's width and height.

The PortraitSpacer positions the portrait image at 5 × min(view.width, view.height), the LandscapeSpacer positions the landscape image at 5 × max(view.width, view.height), and the PositionSpacer has the same width as PortraitSpacer in portrait mode and the same width as LandscapeSpacer in landscape mode.

We multiply everything with 5 so the two images do not overlap. This works for all devices where the following is true

5 × min(view.width, view.height) + max(view.width, view.height) ≤ 5 × max(view.width, view.height)

In landscape mode this would mean

5 / 4 ≤ view.width / view.height

which is the case for all current devices: iPad has the lowest aspect ratio with 4:3 which is still greater than 5:4.

You can then of course configure images per device (iPhone, iPad) in the asset catalog.

0
votes

This is a solution for iPad that can work,

for iPhone you can use size classes and I am not posting that solution here.

The solution is to break up your splash screen image into components and to use constraints to manipulate the image for Portrait vs Landscape.

Here is an example of how I did it.

Create a launch storyboard for iPad

UILaunchStoryboardName~ipad (UILaunchStoryboardName~iphone )

Take your landscape image in my case 2048x1536

I took the landscape image and cut it into three

  1. Center 1536x1536
  2. Left 256x1536
  3. Right 256x1536

On the launch storyboard I created 3 image views with the following constraints

Center Piece:

  • Pin to Top and bottom,
  • center in superview,
  • maintain aspect ratio

Left & Right Piece:

  • 0 Trailing/Leading to Center,
  • Align Top,
  • Equal Height

Then for the Mode of the view for the left and right I changed it from aspect fill to bottom right and bottom left (worked best for me)

I know this seems like overkill for something that should be simple. My reason for using the launch storyboard over launch images was to cut down on app size. I needed fewer launch images and I could use jpeg rather than png