iOS 7 / Xcode 5: Access device launch images programmatically
Solution 1
You can use the launch images without having to include them twice. The key is that when you use an asset catalog, the file names of the images that are included in the app bundle are (sort of) standardized and may not be related to what you've named the original files.
In particular, when you use the LaunchImage image set, the files that end up in the application bundle have names like
- LaunchImage.png
- [email protected]
- [email protected]
- [email protected]
- [email protected]
- LaunchImage-700-Landscape@2x~ipad.png
etc. Note, in particular, they are not named Default.png
or any variation of that. Even if that's what you called the files. Once you've dropped them in one of the wells in the asset catalog, they come out the other end with a standard name.
So [UIImage imageNamed:@"Default"]
won't work because there is no such file in the app bundle. However, [UIImage imageNamed:@"LaunchImage"]
will work (assuming you've filled either the iPhone Portrait 2x well or the pre iOS7 iPhone Portrait 1x well).
The documentation indicates that the imageNamed:
method on UIImage
should auto-magically select the correct version, but I think this only applies to image sets other than the launch image--at least I've not gotten it to work quite correctly (could just be me not doing something right).
So depending on your exact circumstances, you might need to do a little trial and error to get the correct file name. Build and run the app in the simulator and then you can always look in the appropriate subdirectory of ~/Library/Application Support/iPhone Simulator
to verify what the actual file names in the app bundle are.
But again, the main point is that there is no need to include duplicates of the image files and you don't need to make any adjustments to the Copy Bundle Resources
build phase.
Solution 2
You can copy/paste the following code to load your app's launch image at runtime:
// Load launch image
NSString *launchImageName;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
if ([UIScreen mainScreen].bounds.size.height == 480) launchImageName = @"[email protected]"; // iPhone 4/4s, 3.5 inch screen
if ([UIScreen mainScreen].bounds.size.height == 568) launchImageName = @"[email protected]"; // iPhone 5/5s, 4.0 inch screen
if ([UIScreen mainScreen].bounds.size.height == 667) launchImageName = @"[email protected]"; // iPhone 6, 4.7 inch screen
if ([UIScreen mainScreen].bounds.size.height == 736) launchImageName = @"[email protected]"; // iPhone 6+, 5.5 inch screen
}
else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
if ([UIScreen mainScreen].scale == 1) launchImageName = @"LaunchImage-700-Portrait~ipad.png"; // iPad 2
if ([UIScreen mainScreen].scale == 2) launchImageName = @"LaunchImage-700-Portrait@2x~ipad.png"; // Retina iPads
}
self.launchImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:launchImageName]];
Solution 3
Most answers require to create an image name depending on device type, scale, size etc. But as Matthew Burke pointed out, each image inside the launch image catalog will be renamed to "LaunchImage*" and therefore we are able to iterate through our launch images and find the (for the current device) appropriate image. In Objective-C it could look like this:
NSArray *allPngImageNames = [[NSBundle mainBundle] pathsForResourcesOfType:@"png"
inDirectory:nil];
for (NSString *imgName in allPngImageNames){
// Find launch images
if ([imgName containsString:@"LaunchImage"]){
UIImage *img = [UIImage imageNamed:imgName];
// Has image same scale and dimensions as our current device's screen?
if (img.scale == [UIScreen mainScreen].scale && CGSizeEqualToSize(img.size, [UIScreen mainScreen].bounds.size)) {
NSLog(@"Found launch image for current device %@", img.description);
break;
}
}
}
(Please note that this code uses the "containsString" method introduced with iOS 8. For previous iOS versions use "rangeOfString")
Solution 4
A Swift version of the excellent answer by Daniel Witurna that doesn't require checking against a list of all known device types or orientations.
func appLaunchImage() -> UIImage? {
let allPngImageNames = Bundle.main.paths(forResourcesOfType: "png", inDirectory: nil)
for imageName in allPngImageNames
{
// make sure that the image name contains the string 'LaunchImage' and that we can actually create a UIImage from it.
guard
imageName.contains("LaunchImage"),
let image = UIImage(named: imageName)
else { continue }
// if the image has the same scale AND dimensions as the current device's screen...
if (image.scale == UIScreen.main.scale) && (image.size.equalTo(UIScreen.main.bounds.size))
{
return image
}
}
return nil
}
Solution 5
Below is the result when I test in iOS 7.0+, only portrait oritation:
3.5 inch screen: [email protected]
4.0 inch screen: [email protected]
4.7 inch screen: [email protected]
5.5 inch screen: [email protected]
iPad2 : LaunchImage-700-Portrait~ipad.png
Retina iPads : LaunchImage-700-Portrait@2x~ipad.png
Timm
Updated on July 17, 2022Comments
-
Timm almost 2 years
Is there any way to use the apps LaunchImage as a background in an universal iOS app without putting the same image resources in multiple places?
I wasn't able to access the
LaunchImage
files inImages.xcassets
, so I created two new Image Sets "Background Portrait" and "Background Landscape" (since there seems to be no way to put landscape and portrait images into the same set).While this workaround does the jobs, I would hate to include every image into the app twice. This also has a high maintenance cost.
Any advice on how to access the LaunchImage for the current device is appreciated.
GCOLaunchImageTransition must have done the job for iOS < 7.
-
Timm over 10 yearsWhile "Images.xcassets" is already in the "Copy Bundle Resources" section, I can't see it when clicking + to add individual files. And currently "[UIImage imageNamed:@"Default"];" does not work for me.
-
Peter Segerblom over 10 yearsYou need to click first '+' then "add other" then navigate to your Images.xcassets->LaunchImage.launchimage. Images.xcassets is just a folder.
-
john.k.doe over 10 yearsi've upvoted this answer … but i'm also interested in being able to see the image in my .xib, and choosing "LaunchImage" in my .xib works on the device (and probably on the simulator), but just shows the big blue question mark in the .xib . any easy resolution to this part of it?
-
Alex Sorokoletov over 9 yearsSo, did anyone made [UIImage imageNamed:@"LaunchImage"] work?
-
Rolleric over 9 yearsI would think that, in order to avoid searching every time, the resulting imgName (or its lastPathComponent) could be stored as a local User Default.
-
Daniel Witurna over 9 years@Rolleric I thought about your suggestion and probably you are right. The defined launch image will always have the same name, even if you change it, and the user defaults are device bound so this should be fine too. However, I am not sure how costly the search is. Probably it's just a trade-off between speed and storage.
-
Alex Sorokoletov over 9 yearsFor my tamarin app it, unfortunately, didn't
-
Rober over 9 yearsThis solution is not answering the question since it is asked to access the LaunchImage without duplicated assets.
-
bshirley over 9 yearsMy answer is No. You should not try to access the launch image. If you figure out how to access it now, Apple is likely to change it out from under you. If one image the size of the screen is killing your app size, something else is wrong.
-
AlexD over 9 yearsimageNamed didn't work for me on iOS 7 - instead you can use imageWithContentsOfFile
-
Daniel Witurna over 9 years@AlexD I am actually using the function with deployment target iOS 7 but compiling against the iOS 8 SDK. According to Apple's documentation "imageNamed" is available since iOS 2.0 (developer.apple.com/library/ios/documentation/UIKit/Reference/…). The only difference is, that "imageNamed" caches the image in background and "imageWithContentsOfFile" doesn't, which "will keep your single-use image out of the system image cache, potentially improving the memory use characteristics of your app." (Apple Doc)
-
Tom almost 9 yearsThis is by far the best solution
-
alexburtnik over 8 yearsThanks. This solution worked for me, unlike the accepted answer from Matthew Burke
-
AsifHabib over 8 yearsWhich one is for which device ?
-
Dan Rosenstark over 8 yearsWow this annoying, but thanks for sharing your answer. Confirmed that this works...
-
Simo almost 8 yearsMuch prefer this solution over any others here. Just added a Swift version of this answer to help anyone needing one.
-
Ryan H. over 7 yearsThis solution made me realize that the name used to reference the image has nothing to do with the actual filenames in the catalogue. It's a combination of the collection name (
Brand Assets
in my case) plus some "magic" suffixes. This solution would be more foolproof from future changes made by Apple, since the actual image name syntax is undocumented. -
Ryan H. over 7 yearsOne easy optimization is to break out of the for loop when the match is found.
-
Apex over 6 yearsThough xcode (thankfully) modernized a bunch of naming conventions, this foundation is spectacular in xcode 9, swift 3, iOS 10.3 (for maintaining a seamless 'book cover' from app launch LaunchImage to user's first tap). Thank you!! :)
-
SDW over 6 yearsUse [email protected] for iPhone X
-
Dimitris over 6 years@SebastiaandeWeert on the latest Xcode/SDK it seems that the iPhone X splash screen is named
LaunchImage-1100-Portrait-2436h
. -
Ryno C. over 4 yearsSwift 4: This works for Portrait, but not for landscape. You need to change the screenSize to the following line: let screenSize = UIScreen.main.fixedCoordinateSpace.bounds.size. Added Swift 5 with fix