Xcode 5和资产目录:如何引用LaunchImage?

我正在使用Xcode 5的资产目录,我想用我的LaunchImage作为我的主页视图的背景图像(从“加载”到“加载”的过渡看起来非常平常)。

我想使用资产目录中的相同条目来节省空间,而不必在两个不同的图像集中复制图像。

但是,打电话给:

 UIImage *image = [UIImage imageNamed:@"LaunchImage"]; //returns nil 

这是LaunchImage(几乎)完整的列表(不包括没有状态栏的iPad图像):

 - (NSString *)splashImageNameForOrientation:(UIInterfaceOrientation)orientation { CGSize viewSize = self.view.bounds.size; NSString* viewOrientation = @"Portrait"; if (UIDeviceOrientationIsLandscape(orientation)) { viewSize = CGSizeMake(viewSize.height, viewSize.width); viewOrientation = @"Landscape"; } NSArray* imagesDict = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"UILaunchImages"]; for (NSDictionary* dict in imagesDict) { CGSize imageSize = CGSizeFromString(dict[@"UILaunchImageSize"]); if (CGSizeEqualToSize(imageSize, viewSize) && [viewOrientation isEqualToString:dict[@"UILaunchImageOrientation"]]) return dict[@"UILaunchImageName"]; } return nil; } 

LaunchImages是特殊的,实际上并不是设备上的资产目录。 如果您使用iFunBox / iExplorer / etc(或者在模拟器或者编译目录中),您可以看到最终的名字,然后编写代码来使用它们 – 例如。 对于仅限iOS7的iPhone项目,这将设置正确的启动图像:

 NSString *launchImage; if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) && ([UIScreen mainScreen].bounds.size.height > 480.0f)) { launchImage = @"LaunchImage-700-568h"; } else { launchImage = @"LaunchImage-700"; } [self.launchImageView setImage:[UIImage imageNamed:launchImage]]; 

我把这个viewDidLoad。

这不是很理想,如果苹果给我们一个很好的API来做到这一点,那将是非常好的。

我的应用程序目前只支持iOS 7及更高版本。

这是我从资产目录引用启动图像的方式:

 NSDictionary *dict = @{@"320x480" : @"LaunchImage-700", @"320x568" : @"LaunchImage-700-568h", @"375x667" : @"LaunchImage-800-667h", @"414x736" : @"LaunchImage-800-Portrait-736h"}; NSString *key = [NSString stringWithFormat:@"%dx%d", (int)[UIScreen mainScreen].bounds.size.width, (int)[UIScreen mainScreen].bounds.size.height]; UIImage *launchImage = [UIImage imageNamed:dict[key]]; 

如果您想要支持较旧的iOS版本,则可以添加更多的键值对。

这里是基于上面Cherpak Evgeny提供的解决scheme的UIImage类。

UIImage + SplashImage.h

 #import <UIKit/UIKit.h> /** * Category on `UIImage` to access the splash image. **/ @interface UIImage (SplashImage) /** * Return the name of the splash image for a given orientation. * @param orientation The interface orientation. * @return The name of the splash image. **/ + (NSString *)si_splashImageNameForOrientation:(UIInterfaceOrientation)orientation; /** * Returns the splash image for a given orientation. * @param orientation The interface orientation. * @return The splash image. **/ + (UIImage*)si_splashImageForOrientation:(UIInterfaceOrientation)orientation; @end 

UIImage + SplashImage.m

 #import "UIImage+SplashImage.h" @implementation UIImage (SplashImage) + (NSString *)si_splashImageNameForOrientation:(UIInterfaceOrientation)orientation { CGSize viewSize = [UIScreen mainScreen].bounds.size; NSString *viewOrientation = @"Portrait"; if (UIDeviceOrientationIsLandscape(orientation)) { viewSize = CGSizeMake(viewSize.height, viewSize.width); viewOrientation = @"Landscape"; } NSArray* imagesDict = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"UILaunchImages"]; for (NSDictionary *dict in imagesDict) { CGSize imageSize = CGSizeFromString(dict[@"UILaunchImageSize"]); if (CGSizeEqualToSize(imageSize, viewSize) && [viewOrientation isEqualToString:dict[@"UILaunchImageOrientation"]]) return dict[@"UILaunchImageName"]; } return nil; } + (UIImage*)si_splashImageForOrientation:(UIInterfaceOrientation)orientation { NSString *imageName = [self si_splashImageNameForOrientation:orientation]; UIImage *image = [UIImage imageNamed:imageName]; return image; } @end 

@ codeman的答案更新为Swift 1.2:

 func splashImageForOrientation(orientation: UIInterfaceOrientation, size: CGSize) -> String? { var viewSize = size var viewOrientation = "Portrait" if UIInterfaceOrientationIsLandscape(orientation) { viewSize = CGSizeMake(size.height, size.width) viewOrientation = "Landscape" } if let imagesDict = NSBundle.mainBundle().infoDictionary as? [String: AnyObject] { if let imagesArray = imagesDict["UILaunchImages"] as? [[String: String]] { for dict in imagesArray { if let sizeString = dict["UILaunchImageSize"], let imageOrientation = dict["UILaunchImageOrientation"] { let imageSize = CGSizeFromString(sizeString) if CGSizeEqualToSize(imageSize, viewSize) && viewOrientation == imageOrientation { if let imageName = dict["UILaunchImageName"] { return imageName } } } } } } return nil } 

要调用它,并支持iOS 8的旋转:

 override func viewWillAppear(animated: Bool) { if let img = splashImageForOrientation(UIApplication.sharedApplication().statusBarOrientation, size: self.view.bounds.size) { backgroundImage.image = UIImage(named: img) } } override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { let orientation = size.height > size.width ? UIInterfaceOrientation.Portrait : UIInterfaceOrientation.LandscapeLeft if let img = splashImageForOrientation(orientation, size: size) { backgroundImage.image = UIImage(named: img) } } 

正是我所需要的,谢谢!

我只是写了一个通用的方法来获取iPhone和iPad(景观,肖像)的飞溅图像名称,它为我工作,希望它也可以帮助你。 我写了这个与其他SO答案的帮助,感谢@Pichirichi整个列表。

 +(NSString*)getLaunchImageName { NSArray* images= @[@"LaunchImage.png", @"LaunchImage@2x.png",@"LaunchImage-700@2x.png",@"LaunchImage-568h@2x.png",@"LaunchImage-700-568h@2x.png",@"LaunchImage-700-Portrait@2x~ipad.png",@"LaunchImage-Portrait@2x~ipad.png",@"LaunchImage-700-Portrait~ipad.png",@"LaunchImage-Portrait~ipad.png",@"LaunchImage-Landscape@2x~ipad.png",@"LaunchImage-700-Landscape@2x~ipad.png",@"LaunchImage-Landscape~ipad.png",@"LaunchImage-700-Landscape~ipad.png"]; UIImage *splashImage; if ([self isDeviceiPhone]) { if ([self isDeviceiPhone4] && [self isDeviceRetina]) { splashImage = [UIImage imageNamed:images[1]]; if (splashImage.size.width!=0) return images[1]; else return images[2]; } else if ([self isDeviceiPhone5]) { splashImage = [UIImage imageNamed:images[1]]; if (splashImage.size.width!=0) return images[3]; else return images[4]; } else return images[0]; //Non-retina iPhone } else if ([[UIDevice currentDevice] orientation]==UIDeviceOrientationPortrait || [[UIDevice currentDevice] orientation] == UIDeviceOrientationPortraitUpsideDown)//iPad Portrait { if ([self isDeviceRetina]) { splashImage = [UIImage imageNamed:images[5]]; if (splashImage.size.width!=0) return images[5]; else return images[6]; } else { splashImage = [UIImage imageNamed:images[7]]; if (splashImage.size.width!=0) return images[7]; else return images[8]; } } else { if ([self isDeviceRetina]) { splashImage = [UIImage imageNamed:images[9]]; if (splashImage.size.width!=0) return images[9]; else return images[10]; } else { splashImage = [UIImage imageNamed:images[11]]; if (splashImage.size.width!=0) return images[11]; else return images[12]; } } } 

其他效用方法是

 +(BOOL)isDeviceiPhone { if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { return TRUE; } return FALSE; } +(BOOL)isDeviceiPhone4 { if ([[UIScreen mainScreen] bounds].size.height==480) return TRUE; return FALSE; } +(BOOL)isDeviceRetina { if ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)] && ([UIScreen mainScreen].scale == 2.0)) // Retina display { return TRUE; } else // non-Retina display { return FALSE; } } +(BOOL)isDeviceiPhone5 { if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && [[UIScreen mainScreen] bounds].size.height>480) { return TRUE; } return FALSE; } 

Cherpak Evgeny的快速版答案:

  func splashImageForOrientation(orientation: UIInterfaceOrientation) -> String { var viewSize = self.view.bounds.size var viewOrientation = "Portrait" if UIInterfaceOrientationIsLandscape(orientation) { viewSize = CGSizeMake(viewSize.height, viewSize.width) viewOrientation = "Landscape" } let imagesDict = NSBundle.mainBundle().infoDictionary as Dictionary<NSObject,AnyObject>! let imagesArray = imagesDict["UILaunchImages"] as NSArray for dict in imagesArray { let dictNSDict = dict as NSDictionary let imageSize = CGSizeFromString(dictNSDict["UILaunchImageSize"] as String) if CGSizeEqualToSize(imageSize, viewSize) && viewOrientation == (dictNSDict["UILaunchImageOrientation"] as String) { return dictNSDict["UILaunchImageName"] as String } } return "" } 

在Pichirich的回答之后,我将InterfaceBuilder中的launchimage引用为:

“LaunchImage.png”

…和Xcode 5.0.2,它会自动从资产目录中直接提取适当的图像。

这就是我所期待的 – 除了苹果恶意的恶意移动,将“Default.png”重命名为“LaunchImage.png”:)

在文档中明确指出:

“资产目录中的每个集合都有一个名称, 可以使用该名称以编程方式加载集合中包含的任何单个图像。要加载图像,请调用UIImage:ImageNamed:方法,传递包含图像的集合的名称“。

使用Pichirichi的名单有助于解决这种不一致。

人们可以通过一行代码轻松访问启动图像。

  UIImage *myAppsLaunchImage = [UIImage launchImage]; 

请按照以下步骤实现上述function。

第1步。通过创build一个类别扩展UIImage类,并添加以下方法。

 + (UIImage *)launchImage { NSDictionary *dOfLaunchImage = [NSDictionary dictionaryWithObjectsAndKeys: @"LaunchImage-568h@2x.png",@"568,320,2,8,p", // ios 8 - iphone 5 - portrait @"LaunchImage-568h@2x.png",@"568,320,2,8,l", // ios 8 - iphone 5 - landscape @"LaunchImage-700-568h@2x.png",@"568,320,2,7,p", // ios 7 - iphone 5 - portrait @"LaunchImage-700-568h@2x.png",@"568,320,2,7,l", // ios 7 - iphone 5 - landscape @"LaunchImage-700-Landscape@2x~ipad.png",@"1024,768,2,7,l", // ios 7 - ipad retina - landscape @"LaunchImage-700-Landscape~ipad.png",@"1024,768,1,7,l", // ios 7 - ipad regular - landscape @"LaunchImage-700-Portrait@2x~ipad.png",@"1024,768,2,7,p", // ios 7 - ipad retina - portrait @"LaunchImage-700-Portrait~ipad.png",@"1024,768,1,7,p", // ios 7 - ipad regular - portrait @"LaunchImage-700@2x.png",@"480,320,2,7,p", // ios 7 - iphone 4/4s retina - portrait @"LaunchImage-700@2x.png",@"480,320,2,7,l", // ios 7 - iphone 4/4s retina - landscape @"LaunchImage-Landscape@2x~ipad.png",@"1024,768,2,8,l", // ios 8 - ipad retina - landscape @"LaunchImage-Landscape~ipad.png",@"1024,768,1,8,l", // ios 8 - ipad regular - landscape @"LaunchImage-Portrait@2x~ipad.png",@"1024,768,2,8,p", // ios 8 - ipad retina - portrait @"LaunchImage-Portrait~ipad.png",@"1024,768,1,8,l", // ios 8 - ipad regular - portrait @"LaunchImage.png",@"480,320,1,7,p", // ios 6 - iphone 3g/3gs - portrait @"LaunchImage.png",@"480,320,1,7,l", // ios 6 - iphone 3g/3gs - landscape @"LaunchImage@2x.png",@"480,320,2,8,p", // ios 6,7,8 - iphone 4/4s - portrait @"LaunchImage@2x.png",@"480,320,2,8,l", // ios 6,7,8 - iphone 4/4s - landscape @"LaunchImage-800-667h@2x.png",@"667,375,2,8,p", // ios 8 - iphone 6 - portrait @"LaunchImage-800-667h@2x.png",@"667,375,2,8,l", // ios 8 - iphone 6 - landscape @"LaunchImage-800-Portrait-736h@3x.png",@"736,414,3,8,p", // ios 8 - iphone 6 plus - portrait @"LaunchImage-800-Landscape-736h@3x.png",@"736,414,3,8,l", // ios 8 - iphone 6 plus - landscape nil]; NSInteger width = ([UIScreen mainScreen].bounds.size.width>[UIScreen mainScreen].bounds.size.height)?[UIScreen mainScreen].bounds.size.width:[UIScreen mainScreen].bounds.size.height; NSInteger height = ([UIScreen mainScreen].bounds.size.width>[UIScreen mainScreen].bounds.size.height)?[UIScreen mainScreen].bounds.size.height:[UIScreen mainScreen].bounds.size.width; NSInteger os = [[[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:@"."] objectAtIndex:0] integerValue]; NSString *strOrientation = UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation])?@"l":@"p"; NSString *strImageName = [NSString stringWithFormat:@"%li,%li,%li,%li,%@",width,height,(NSInteger)[UIScreen mainScreen].scale,os,strOrientation]; UIImage *imageToReturn = [UIImage imageNamed:[dOfLaunchImage valueForKey:strImageName]]; if([strOrientation isEqualToString:@"l"] && [strImageName rangeOfString:@"Landscape"].length==0) { imageToReturn = [UIImage rotate:imageToReturn orientation:UIImageOrientationRight]; } return imageToReturn; } 

步骤2.上面的方法应该通过将以下代码也添加到UIImage相同类别中来工作

 static inline double radians (double degrees) {return degrees * M_PI/180;} + (UIImage *)rotate:(UIImage*)src orientation:(UIImageOrientation) orientation { UIGraphicsBeginImageContext(src.size); CGContextRef context = UIGraphicsGetCurrentContext(); if (orientation == UIImageOrientationRight) { CGContextRotateCTM (context, radians(90)); } else if (orientation == UIImageOrientationLeft) { CGContextRotateCTM (context, radians(-90)); } else if (orientation == UIImageOrientationDown) { // NOTHING } else if (orientation == UIImageOrientationUp) { CGContextRotateCTM (context, radians(90)); } [src drawAtPoint:CGPointMake(0, 0)]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; } 

我意识到,这不一定是每个人的最佳解决scheme,但最简单的(和最小的错误,恕我直言)方式做到这一点是通过在您的Images.xcassets目录中单独条目。 我把它叫做SplashImage

当您添加新条目时,请确保不要select“新启动映像”作为选项。 相反,请select通用的“新build图像集”。 接下来,打开检查员并select相关选项。 如果您只为视网膜设备build设,那么您可以select以下选项:

图像检查员

这会给你四个条目(iPhone 4S,iPhone 5(S,C),iPhone 6和iPhone 6 Plus)。

图片

这些图像对应的文件如下:

 | Resolution (Xcode entry) | Launch Image name | Device | |--------------------------|---------------------|------------------| | 1x | Default-750.png | iPhone 6 | | 2x | Default@2x.png | iPhone 4S | | Retina 4 2x | Default-568h@2x.png | iPhone 5, 5s, 5c | | 3x | Default-1242.png | iPhone 6 Plus | 

当然,完成这些之后,你可以简单地使用[UIImage imageNamed:@"SplashImage"]

在Pichirichi的答案帮助下,我实现了以下类别(iOS 7 + ): UIImage + AssetLaunchImage

它实际上不过是即时生成名称,但可能会有所帮助。