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

tob*_*pwn 102 xcode ios ios7 xcode5 asset-catalog

我正在使用Xcode 5的资产目录,我想用我LaunchImage作为我家视图的背景图像(这是一种非常常见的做法,使得从'加载'到'加载'的过渡看起来很流畅).

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

但是,致电:

UIImage *image = [UIImage imageNamed:@"LaunchImage"]; //returns nil
Run Code Online (Sandbox Code Playgroud)

Pic*_*chi 83

这是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 Portrait)
  • LaunchImage-800-Landscape-736h@3x.png(iPhone 6 Plus横向)
  • LaunchImage-1100-Portrait-2436h@3x.png(iPhone X Portrait)
  • LaunchImage-1100-Landscape-2436h@3x.png(iPhone X Landscape)

  • 令人难以置信的是,XCode会自动为这些图像资源创建一个文件名,并让你跳过箍来弄清楚如何直接访问它们...... (4认同)
  • LaunchImage-800-Portrait-736h@3x.png对我不起作用 (2认同)
  • 我抓住了它:它意味着iOS 7和8 (2认同)

Che*_*eny 67

- (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;
}
Run Code Online (Sandbox Code Playgroud)

  • 但是很棒的主意.但对于具有不透明状态栏的屏幕不起作用.因此需要将self.view.bounds.size更改为[UIScreen mainScreen] .bounds.size (3认同)

Jos*_*phH 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]];
Run Code Online (Sandbox Code Playgroud)

我把它放到viewDidLoad中.

这不是很理想,如果Apple能给我们一个很好的API来做这件事会很棒.

  • 这对我有用,但我真的希望有一种更简单的方式来引用启动图像. (2认同)

non*_*ive 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]];
Run Code Online (Sandbox Code Playgroud)

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


vil*_*ovi 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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)


Ant*_*ott 9

@ 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

}
Run Code Online (Sandbox Code Playgroud)

要调用它,并支持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)
    }

}
Run Code Online (Sandbox Code Playgroud)

正是我需要的,谢谢!


zah*_*eer 7

我刚刚写了一个通用方法来获取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];
    }
 }
}
Run Code Online (Sandbox Code Playgroud)

其他实用方法是

+(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;
}
Run Code Online (Sandbox Code Playgroud)


cod*_*man 7

Swift版本的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 ""
    }
Run Code Online (Sandbox Code Playgroud)


Ada*_*dam 5

按照@ Pichirich的回答,我在InterfaceBuilder中引用了我的launchimage:

"LaunchImage.png"

...并且使用Xcode 5.0.2,它会自动从资产目录中直接提取相应的图像.

这就是我所期望的 - 除了苹果公司将"Default.png"重命名为"LaunchImage.png"的恶意恶作剧:)