2013-10-01 38 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) 
    } 

} 

這正是我需要的,謝謝!

相關問題