Xcode 5和资产目录:如何引用LaunchImage?
我正在使用Xcode 5的资产目录,我想用我的LaunchImage
作为我的主页视图的背景图像(从“加载”到“加载”的过渡看起来非常平常)。
我想使用资产目录中的相同条目来节省空间,而不必在两个不同的图像集中复制图像。
但是,打电话给:
UIImage *image = [UIImage imageNamed:@"LaunchImage"]; //returns nil
这是LaunchImage(几乎)完整的列表(不包括没有状态栏的iPad图像):
- LaunchImage-568h@2x.png
- LaunchImage-700-568h@2x.png
- LaunchImage-700-Landscape@2x~ipad.png
- LaunchImage-700-景观〜ipad.png
- LaunchImage-700-Portrait@2x~ipad.png
- LaunchImage-700-肖像〜ipad.png
- LaunchImage-700@2x.png
- LaunchImage-Landscape@2x~ipad.png
- LaunchImage – 风景〜ipad.png
- LaunchImage-Portrait@2x~ipad.png
- LaunchImage画像〜ipad.png
- LaunchImage.png
- LaunchImage@2x.png
- LaunchImage-800-667h@2x.png(iPhone 6)
- LaunchImage-800-Portrait-736h@3x.png(iPhone 6 Plus肖像)
- LaunchImage-800-Landscape-736h@3x.png(iPhone 6 Plus景观)
- (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
它实际上不过是即时生成名称,但可能会有所帮助。