iOS 7 / Xcode 5:访问设备以编程方式启动图像

有没有办法在通用的iOS应用程序中使用应用程序LaunchImage作为背景,而无需在多个地方放置相同的图像资源?

我无法访问LaunchImage中的LaunchImage文件,所以我创build了两个新的图像集“背景人像”和“背景风景”(因为似乎无法将风景和肖像图像放入同一个集合) 。

虽然这个解决方法做的工作,我不希望包括每个图像的应用程序两次。 这也有很高的维护成本。

有关如何访问当前设备的LaunchImage的任何build议,赞赏。

GCOLaunchImageTransition必须完成iOS <7的工作。

您可以使用启动图像,而不必包含它们两次。 关键在于,当您使用资产目录时,应用程序包中包含的图像的文件名称是(有点)标准化的,可能与您命名原始文件不相关。

特别是,当您使用LaunchImage映像集时,最终在应用程序包中的文件具有类似的名称

等等。特别的是,它们并不被命名为Default.png或者其他任何变体。 即使这就是你所说的文件。 一旦你把它们放在资产目录中的一个井中 ,它们就会以标准名称出现在另一端。

所以[UIImage imageNamed:@"Default"]将不起作用,因为应用程序包中没有这样的文件。 不过, [UIImage imageNamed:@"LaunchImage"]将会起作用(假设你已经填充了iPhone Portrait 2x或者iOS7以前的 iPhone Portrait 1x)。

该文件表明, UIImage上的imageNamed:方法应该自动地魔术般地select正确的版本,但我认为这只适用于除启动图像以外的图像集 – 至less我没有得到它的工作相当正确( 可能只是我不做正确的事情 )。

因此,根据您的具体情况,您可能需要进行一些试验和错误以获取正确的文件名。 在模拟器中构build并运行应用程序,然后可以始终查看~/Library/Application Support/iPhone Simulator的相应子目录,以validation应用程序包中的实际文件名是什么。

但是,重要的一点是,不需要包含图像文件的副本,也不需要对“ Copy Bundle Resources构build阶段进行任何调整。

您可以复制/粘贴以下代码以在运行时加载应用的启动映像:

 // Load launch image NSString *launchImageName; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { if ([UIScreen mainScreen].bounds.size.height == 480) launchImageName = @"LaunchImage-700@2x.png"; // iPhone 4/4s, 3.5 inch screen if ([UIScreen mainScreen].bounds.size.height == 568) launchImageName = @"LaunchImage-700-568h@2x.png"; // iPhone 5/5s, 4.0 inch screen if ([UIScreen mainScreen].bounds.size.height == 667) launchImageName = @"LaunchImage-800-667h@2x.png"; // iPhone 6, 4.7 inch screen if ([UIScreen mainScreen].bounds.size.height == 736) launchImageName = @"LaunchImage-800-Portrait-736h@3x.png"; // iPhone 6+, 5.5 inch screen } else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { if ([UIScreen mainScreen].scale == 1) launchImageName = @"LaunchImage-700-Portrait~ipad.png"; // iPad 2 if ([UIScreen mainScreen].scale == 2) launchImageName = @"LaunchImage-700-Portrait@2x~ipad.png"; // Retina iPads } self.launchImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:launchImageName]]; 

大多数答案都需要根据设备types,比例,大小等来创build图像名称。但正如Matthew Burke所指出的,发布图像目录中的每个图像将被重命名为“LaunchImage *”,因此我们可以遍历我们的发布图像并find(为当前设备)适当的图像。 在Objective-C中,它可能看起来像这样:

 NSArray *allPngImageNames = [[NSBundle mainBundle] pathsForResourcesOfType:@"png" inDirectory:nil]; for (NSString *imgName in allPngImageNames){ // Find launch images if ([imgName containsString:@"LaunchImage"]){ UIImage *img = [UIImage imageNamed:imgName]; // Has image same scale and dimensions as our current device's screen? if (img.scale == [UIScreen mainScreen].scale && CGSizeEqualToSize(img.size, [UIScreen mainScreen].bounds.size)) { NSLog(@"Found launch image for current device %@", img.description); break; } } } 

(请注意,此代码使用iOS 8中引入的“containsString”方法。对于之前的iOS版本,使用“rangeOfString”)

下面是我在iOS 7.0+testing的结果,只有肖像定位:

 3.5 inch screen: LaunchImage-700@2x.png 4.0 inch screen: LaunchImage-700-568h@2x.png 4.7 inch screen: LaunchImage-800-667h@2x.png 5.5 inch screen: LaunchImage-800-Portrait-736h@3x.png iPad2 : LaunchImage-700-Portrait~ipad.png Retina iPads : LaunchImage-700-Portrait@2x~ipad.png 

Daniel Witurna的一个很好的答案 ,不需要检查所有已知设备types或方向的列表。

 func appLaunchImage() -> UIImage? { let allPngImageNames = NSBundle.mainBundle().pathsForResourcesOfType("png", inDirectory: nil) for imageName in allPngImageNames { guard imageName.containsString("LaunchImage") else { continue } guard let image = UIImage(named: imageName) else { continue } // if the image has the same scale AND dimensions as the current device's screen... if (image.scale == UIScreen.mainScreen().scale) && (CGSizeEqualToSize(image.size, UIScreen.mainScreen().bounds.size)) { return image } } return nil } 

Swift中用于在运行时获取启动映像名称的简洁函数:

 func launchImageName() -> String { switch (UI_USER_INTERFACE_IDIOM(), UIScreen.mainScreen().scale, UIScreen.mainScreen().bounds.size.height) { case (.Phone, _, 480): return "LaunchImage-700@2x.png" case (.Phone, _, 568): return "LaunchImage-700-568h@2x.png" case (.Phone, _, 667): return "LaunchImage-800-667h@2x.png" case (.Phone, _, 736): return "LaunchImage-800-Portrait-736h@3x.png" case (.Pad, 1, _): return "LaunchImage-700-Portrait~ipad.png" case (.Pad, 2, _): return "LaunchImage-700-Portrait@2x~ipad.png" default: return "LaunchImage" } } 

我不知道这是否是通过代码访问的意思。 但是如果你select你的“项目 – >目标 – >构build阶段 – >复制束资源”,点击“+”和“添加其他”导航到你的Images.xcassets-> LaunchImage.launchimage并select你想使用的任何PNG并点击“打开”。 现在你可以使用像[UIImage imageNamed:@"Default"];

如果你需要确定设备,我使用下面的代码(这是一个快速和肮脏的一点点,但它的窍门)

 if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone ){ CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height; CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; if( screenHeight < screenWidth ){ screenHeight = screenWidth; } if( screenHeight > 480 && screenHeight < 667 ){ DLog(@"iPhone 5/5s"); } else if ( screenHeight > 480 && screenHeight < 736 ){ DLog(@"iPhone 6"); } else if ( screenHeight > 480 ){ DLog(@"iPhone 6 Plus"); } else { DLog(@"iPhone 4/4s"); } } 

马修伯克的答案是正确的答案。 下面是我正在使用的代码来获得这个工作在iOS9 / Xcode7,build立一个应用程序的iOS7和以上,为iPhone和iPad,横向允许。

首先,详细阐述一下:在iOS8 / Xcode6中,如果您使用的是故事板启动屏幕文件,则在应用程序启动时,该应用程序会以正确的分辨率为该启动屏幕文件创build2个图像(一个人像,一个风景)你的设备,你能够从文件path获取该图像。 (我相信它存储在Library / LaunchImage文件夹中)。

但是,在iOS9 / XCode 7中,不再创build此映像(尽pipe在快照文件夹中创build了一个快照,但其名称随时都会更改),因此如果要在代码中的其他位置使用LaunchImage,您必须使用启动图像源(由于应用程序细化,最好通过资产目录)。 现在,正如马修·伯克(Matthew Burke)所解释的那样,你只能这样做,

 let launchImage = UIImage(named: "LaunchImage") 

即使您的资产目录中的图像名称是LaunchImage,Xcode / iOS9也不会让您。

幸运的是,您不必在您的资产目录中再次包含启动图像。 我说幸运的是,如果你正在为所有设备制作应用程序,这意味着你的应用程序下载大小会增加20MB。

那么,如何到达那些启animation面呢? 那么,这里是步骤:

  1. 创build您的启动图像,并把它们放在您的资产目录。 图像的名称并不重要。
  2. 确保您的启动屏幕文件(在目标的常规设置下)为空,并从您的设备和模拟器中删除您的应用程序。 (只是删除文件名和重新运行不会这样做,你必须先删除你的应用程序)
  3. 在模拟器中运行你的应用程序,并进入〜/库/应用程序支持/ iPhone模拟器文件夹,并在那里find你的应用程序。 (因为文件夹名称是不确定的,所以显示一下包的内容。)在那里你会看到几个以“LaunchImage- …”开头的图像文件。在我的例子中,有9个图像因为我正在为iPhone7和iOS7开发应用程序。
  4. 然后,在您的代码中,您需要确定您的应用正在运行的设备以及纵向或横向,然后决定使用哪个图像。 为了使这一点更容易我使用这个框架: https : //github.com/InderKumarRathore/DeviceGuru 。 是洁具,它不包括最新的设备(iPhone 6s和iPhone 6s plus),所以你必须在他的swift文件中添加一行。 然后,把下面的一段代码放在你想要的launchImage的vc中,

     func launchImage() -> UIImage? { if let launchImageName = launcheImageName() { print(launchImageName) return UIImage(named: launchImageName) } else { print("no launch image") return nil } } func launcheImageName() -> String? { let HD35 = "LaunchImage-700@2x.png" let HD40 = "LaunchImage-700-568h@2x" let HD47 = "LaunchImage-800-667h@2x.png" var HD55 = "LaunchImage-800-Portrait-736h@3x.png" var padHD = "LaunchImage-700-Portrait@2x~ipad.png" var pad = "LaunchImage-700-Portrait~ipad.png" if UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft || UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeRight { HD55 = "LaunchImage-800-Landscape-736h@3x.png" padHD = "LaunchImage-700-Landscape@2x~ipad.png" pad = "LaunchImage-700-Landscape~ipad.png" } let hardware = hardwareString() if (hardware == "iPhone1,1") { return HD35 } if (hardware == "iPhone1,2") { return HD35 } if (hardware == "iPhone2,1") { return HD35 } if (hardware == "iPhone3,1") { return HD35 } if (hardware == "iPhone3,2") { return HD35 } if (hardware == "iPhone3,3") { return HD35 } if (hardware == "iPhone4,1") { return HD35 } if (hardware == "iPhone5,1") { return HD40 } if (hardware == "iPhone5,2") { return HD40 } if (hardware == "iPhone5,3") { return HD40 } if (hardware == "iPhone5,4") { return HD40 } if (hardware == "iPhone6,1") { return HD40 } if (hardware == "iPhone6,2") { return HD40 } if (hardware == "iPhone7,1") { return HD55 } if (hardware == "iPhone7,2") { return HD47 } if (hardware == "iPhone8,1") { return HD55 } if (hardware == "iPhone8,2") { return HD47 } if (hardware == "iPod1,1") { return HD35 } if (hardware == "iPod2,1") { return HD35 } if (hardware == "iPod3,1") { return HD35 } if (hardware == "iPod4,1") { return HD35 } if (hardware == "iPod5,1") { return HD40 } if (hardware == "iPad1,1") { return pad } if (hardware == "iPad1,2") { return pad } if (hardware == "iPad2,1") { return pad } if (hardware == "iPad2,2") { return pad } if (hardware == "iPad2,3") { return pad } if (hardware == "iPad2,4") { return pad } if (hardware == "iPad2,5") { return pad } if (hardware == "iPad2,6") { return pad } if (hardware == "iPad2,7") { return pad } if (hardware == "iPad3,1") { return padHD } if (hardware == "iPad3,2") { return padHD } if (hardware == "iPad3,3") { return padHD } if (hardware == "iPad3,4") { return padHD } if (hardware == "iPad3,5") { return padHD } if (hardware == "iPad3,6") { return padHD } if (hardware == "iPad4,1") { return padHD } if (hardware == "iPad4,2") { return padHD } if (hardware == "iPad4,3") { return padHD } if (hardware == "iPad4,4") { return padHD } if (hardware == "iPad4,5") { return padHD } if (hardware == "iPad4,6") { return padHD } if (hardware == "iPad4,7") { return padHD } if (hardware == "iPad4,8") { return padHD } if (hardware == "iPad5,3") { return padHD } if (hardware == "iPad5,4") { return padHD } if (hardware == "i386") { return HD55 } if (hardware == "x86_64") { return HD55 } if (hardware.hasPrefix("iPhone")) { return HD55 } if (hardware.hasPrefix("iPod")) { return HD55 } if (hardware.hasPrefix("iPad")) { return padHD } //log message that your device is not present in the list logMessage(hardware) return nil } 
  if (IS_IPHONE_4_OR_LESS) { self.imageView.image = [UIImage imageNamed:@"LaunchImage-700@2x.png"]; } else if (IS_IPHONE_5){ self.imageView.image = [UIImage imageNamed:@"LaunchImage-700-568h@2x.png"]; } else if (IS_IPHONE_6){ self.imageView.image = [UIImage imageNamed:@"LaunchImage-800-667h@2x.png"]; } else if (IS_IPHONE_6P){ self.imageView.image = [UIImage imageNamed:@"LaunchImage-800-Portrait-736h@3x.png"]; } 

这里是基于Daniel Witurna解决scheme的修改代码。 此代码段使用谓词来过滤来自捆绑映像列表的启动映像名称。 谓词将潜在地避免循环次数从图像path数组中过滤启动图像。

 -(NSString *)getLaunchImageName{ NSArray *allPngImageNames = [[NSBundle mainBundle] pathsForResourcesOfType:@"png" inDirectory:nil]; NSString *expression=[NSString stringWithFormat:@"SELF contains '%@'",@"LaunchImage"]; NSArray *res = [allPngImageNames filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:expression]]; NSString *launchImageName; for (launchImageName in res){ { UIImage *img = [UIImage imageNamed:launchImageName]; // Has image same scale and dimensions as our current device's screen? if (img.scale == [UIScreen mainScreen].scale && CGSizeEqualToSize(img.size, [UIScreen mainScreen].bounds.size)) { NSLog(@"Found launch image for current device %@", img.description); break; } } } return launchImageName; } 

一旦创build了Images.xcassets ,只需将LaunchImage重命名为Default

如果您支持iOS5和iOS6,这将节省很多麻烦。

构build时,“文件夹”/类别的实际名称将会跟随在资产上。 马修伯克说的其他一切都是真实的)

在您的项目中创build一个新的组,不受任何物理目录的支持。 直接从LaunchImage.launchimage导入到该组中的启动图像。 瞧。

由于“LaunchImage”资产实际上是一种自定义的野兽…

我的build议是创build一个重复的图像(或实际需要的子集)的辅助资产目录。

我叫我的FauxLaunchImage 。 他们可以像你想要的那样访问它

 [UIImage imageNamed:@"FauxLaunchImage"];