2013-10-01 40 views
99

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

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

但是,调用:

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

回答

53

的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来做到这一点,那将是非常好的。

+2

这对我有用,但我真的希望有一个简单的方法来引用启动图像。 – Zorayr

+0

也许修正在Xcode 5.0.2中 - 见下文,似乎只适用于我参考“LaunchImage.png” – Adam

+1

@Adam如果那是真的,我会爱上它!我刚刚尝试过iphone5s/xcode5.0.2/ios7.0.4,[UIImage imageNamed:@“LaunchImage.png”]给我零。 – JosephH

83

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

+2

[email protected]不适用于我 – Awesomeness

+0

任何人都知道没有状态栏的iPad图像? –

+1

@Mohamed Hafez:Pichirichi确实将他们列入了他的名单。它们是LaunchImage-Portrait〜ipad.png,[email protected]~ipad.png,LaunchImage-Landscape〜ipad.png和[email protected]~ipad.png。 –

5

继@ Pichirich的回答,我引用我的launchimage InterfaceBuilder下为:

“ LaunchImage.png“

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

这是我所期待 - 除了苹果的默默重命名“为Default.png”到“LaunchImage.png”恶毒肮脏举动:)

+0

还有一件事值得注意。这些图片的尺寸应该与Apple建议的尺寸完全相同(例如320x480的LaunchImage适用于iOS 5-6 iPhone 3GS),否则在初始化后它将为'nil'。 –

3

documentation有明确规定:

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

使用Pichirichi的列表有助于解决这种不一致问题。

+1

请注意“集合的名称”部分。看看我的资产目录,我有一个名为“LaunchImage”的集合。为了加载启动图像,我调用了:'UIImageView * myView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@“LaunchImage”]];'很棒! – leanne

+1

不需要使用Pichirichi的列表(认为这仍然是非常棒的信息) - 只需使用资产目录的“设置”的名称即可。 – leanne

+2

对我来说,这并不适用于Xcode 6.0.1和iOS 8上的Launch Image。LaunchImage似乎很特别,因为这些图像单独存在于已编译的应用程序包中,并且不会保留在xcasset bundle文件夹中。 – auco

7

我刚刚写了一个通用的方法来获取iPhone和iPad的飞溅图像名称(横向,纵向),它为我工作,希望它也可以帮助你。我在其他SO答案的帮助下写了这篇文章,感谢@Pichirichi的整个列表。

+(NSString*)getLaunchImageName 
{ 

NSArray* images= @[@"LaunchImage.png", @"[email protected]",@"[email protected]",@"[email protected]",@"[email protected]",@"[email protected]~ipad.png",@"[email protected]~ipad.png",@"LaunchImage-700-Portrait~ipad.png",@"LaunchImage-Portrait~ipad.png",@"[email protected]~ipad.png",@"[email protected]~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; 
} 
+0

isdeviceiPhone4的这段代码实际上有一个小错误:[[UIScreen mainScreen]界限]现在会根据您在iOS 8下的方向而改变。需要将它明确地转换为像素:'[screen.coordinateSpace convertRect:screen.bounds toCoordinateSpace:screen.fixedCoordinateSpace]',但是一定要测试你是否在iOS 8上,否则会崩溃。 –

+0

感谢@Hafez指出这一点,我将在iOS 8上测试它,并尽快更新答案。 – zaheer

2

我意识到,这不一定对每个人都是最好的解决方案,但最简单的(和最不容易出错的,恕我直言)的方式来做到这一点是通过使在Images.xcassets目录中单独输入。我称之为SplashImage

当您添加新条目时,请确保不是以选择“新启动图像”作为选项。相反,请选择通用的“新建图像集”。接下来,打开检查员并选择相关选项。如果您正在为唯一视网膜显示设备上,因为我是,你可以选择以下内容:

image inspector

这会使你的四个项目(iPhone 4S的,iPhone 5(S,C),iPhone 6 ,和iPhone 6 Plus)。是

images

相应的图像中的文件如下:

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

当然,你已经这样做了之后,你可以简单地使用[UIImage imageNamed:@"SplashImage"]

+1

有趣的想法,但它不适用于iPhone 6.它仍然加载iPhone 6模拟器上的[email protected]图像。 – nonamelive

+0

使用这种方法,您还应该注意一组启动图像以适应横向。 – berec

27

我的应用程序目前只支持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您可以添加更多的键值对。

+1

请注意,从iOS 8开始,“UIScreen.mainScreen.bounds”根据当前界面方向而有所不同。请参阅http://stackoverflow.com/a/24153540/158525 –

+1

感谢您的支持,正是我一直在寻找的! –

+0

感谢htis,任何访问App图标的方法? – AsifHabib

3

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

UIImage *myAppsLaunchImage = [UIImage launchImage]; 

请按照下面给出的步骤实现上述功能。

步骤1。通过创建类别&添加以下方法来扩展UIImage类。

+ (UIImage *)launchImage { 
    NSDictionary *dOfLaunchImage = [NSDictionary dictionaryWithObjectsAndKeys: 
            @"[email protected]",@"568,320,2,8,p", // ios 8 - iphone 5 - portrait 
            @"[email protected]",@"568,320,2,8,l", // ios 8 - iphone 5 - landscape 
            @"[email protected]",@"568,320,2,7,p", // ios 7 - iphone 5 - portrait 
            @"[email protected]",@"568,320,2,7,l", // ios 7 - iphone 5 - landscape 
            @"[email protected]~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 
            @"[email protected]~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 
            @"[email protected]",@"480,320,2,7,p", // ios 7 - iphone 4/4s retina - portrait 
            @"[email protected]",@"480,320,2,7,l", // ios 7 - iphone 4/4s retina - landscape 
            @"[email protected]~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 
            @"[email protected]~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 
            @"[email protected]",@"480,320,2,8,p", // ios 6,7,8 - iphone 4/4s - portrait 
            @"[email protected]",@"480,320,2,8,l", // ios 6,7,8 - iphone 4/4s - landscape 
            @"[email protected]",@"667,375,2,8,p", // ios 8 - iphone 6 - portrait 
            @"[email protected]",@"667,375,2,8,l", // ios 8 - iphone 6 - landscape 
            @"[email protected]",@"736,414,3,8,p", // ios 8 - iphone 6 plus - portrait 
            @"[email protected]",@"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])[email protected]"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; 
} 
+0

优秀的答案,谢谢! – dortzur

+1

现在iPhone X发布图像的名称是什么? – RPM

2

随着Pichirichi的答案,我已经实现了以下类别的帮助同一类别来工作(iOS版7+): UIImage+AssetLaunchImage

它实际上只是在fl上生成名称Ÿ,但可能会有所帮助。

60
- (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; 
} 
+1

工程很棒。巧妙和优雅的方法来搜索主包的信息词典的可用启动图像,然后选择具有匹配分辨率的一个! – iOSX

+0

优秀的方法。恭喜。 – vilanovi

+0

这不适用于iOS 6,因为视图高度小于状态栏屏幕的高度。 – jlukanta

10

这里是基于上述Cherpak Evgeny提供的解决方案的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 
+1

使用它,像魅力一样工作。谢谢! – livingtech

+0

imageNamed将图像推送到系统缓存,但启动图像有时非常大,所以它在内存中,直到缓存刷新它 –

7

Cherpak叶夫根的答案的斯威夫特版本:

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 "" 
    } 
9

@ codeman的答案更新f或雨燕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) 
    } 

} 

这正是我需要的,谢谢!

相关问题