有没有办法将应用程序LaunchImage用作通用iOS应用程序中的背景,而无需在多个位置放置相同的图像资源?
我无法访问LaunchImage
中的Images.xcassets
文件,因此我创建了两个新的图像集“背景肖像”和“背景风景”(因为似乎无法放置)将风景和肖像图像放入同一组中。)
虽然这个解决方法完成了这些工作,但我不愿意将每个图像都包含在应用程序中两次。这也具有很高的维护成本。
有关如何访问当前设备的LaunchImage的任何建议都表示赞赏。
GCOLaunchImageTransition必须完成iOS的工作< 7。
答案 0 :(得分:56)
您可以复制/粘贴以下代码,以便在运行时加载应用的启动图像:
// 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]];
答案 1 :(得分:42)
您可以使用启动图像,而无需包含它们两次。关键是当您使用资产目录时,应用程序包中包含的图像的文件名是(有点)标准化的,可能与您为原始文件命名的内容无关。
特别是,当您使用LaunchImage图像集时,最终在应用程序包中的文件具有类似
的名称等。请注意,特别是它们未命名为Default.png
或其任何变体。即使那就是你所谓的文件。一旦你将它们放入资产目录中的一个井中,它们就会以标准名称出现在另一端。
因此,[UIImage imageNamed:@"Default"]
无效,因为应用包中没有此类文件。但是,[UIImage imageNamed:@"LaunchImage"]
将起作用(假设您已经填充了iPhone Portrait 2x或者 pre iOS7 iPhone Portrait 1x)。
文档指出imageNamed:
上的UIImage
方法应该自动选择正确的版本,但我认为这仅适用于启动图像以外的图像集 - 至少我是没有让它正常工作(可能只是我没有做正确的事情)。
因此,根据您的具体情况,您可能需要进行一些试验和错误才能获得正确的文件名。在模拟器中构建并运行应用程序,然后您可以始终查看~/Library/Application Support/iPhone Simulator
的相应子目录,以验证应用程序包中的实际文件名是什么。
但同样重要的是,重点是不需要包含图像文件的副本,也不需要对Copy Bundle Resources
构建阶段进行任何调整。
答案 2 :(得分:41)
大多数答案都需要根据设备类型,比例,大小等创建图像名称。但正如Matthew Burke指出的那样,启动图像目录中的每个图像都将重命名为" LaunchImage *"因此我们能够遍历我们的发布图像并找到(对于当前设备)适当的图像。在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")
答案 3 :(得分:10)
以下是我在iOS 7.0+中测试时的结果,只有纵向:
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
答案 4 :(得分:9)
Daniel Witurna的优秀answer的Swift版本,不需要检查所有已知设备类型或方向的列表。
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
}
答案 5 :(得分:4)
Info.plist
包含启动图像信息,包括启动图像的名称。
目标-C:
- (UIImage *)getCurrentLaunchImage {
CGSize screenSize = [UIScreen mainScreen].bounds.size;
NSString *interfaceOrientation = nil;
if (([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown) ||
([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortrait)) {
interfaceOrientation = @"Portrait";
} else {
interfaceOrientation = @"Landscape";
}
NSString *launchImageName = nil;
NSArray *launchImages = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"UILaunchImages"];
for (NSDictionary *launchImage in launchImages) {
CGSize launchImageSize = CGSizeFromString(launchImage[@"UILaunchImageSize"]);
NSString *launchImageOrientation = launchImage[@"UILaunchImageOrientation"];
if (CGSizeEqualToSize(launchImageSize, screenSize) &&
[launchImageOrientation isEqualToString:interfaceOrientation]) {
launchImageName = launchImage[@"UILaunchImageName"];
break;
}
}
return [UIImage imageNamed:launchImageName];
}
斯威夫特4:
func getCurrentLaunchImage() -> UIImage? {
guard let launchImages = Bundle.main.infoDictionary?["UILaunchImages"] as? [[String: Any]] else { return nil }
let screenSize = UIScreen.main.bounds.size
var interfaceOrientation: String
switch UIApplication.shared.statusBarOrientation {
case .portrait,
.portraitUpsideDown:
interfaceOrientation = "Portrait"
default:
interfaceOrientation = "Landscape"
}
for launchImage in launchImages {
guard let imageSize = launchImage["UILaunchImageSize"] as? String else { continue }
let launchImageSize = CGSizeFromString(imageSize)
guard let launchImageOrientation = launchImage["UILaunchImageOrientation"] as? String else { continue }
if
launchImageSize.equalTo(screenSize),
launchImageOrientation == interfaceOrientation,
let launchImageName = launchImage["UILaunchImageName"] as? String {
return UIImage(named: launchImageName)
}
}
return nil
}
答案 6 :(得分:1)
我不知道这是否是您通过代码访问的意思。但是,如果您选择“project-> target->构建阶段 - >复制捆绑资源”,请单击“+”和“添加其他”导航到您的Images.xcassets-> LaunchImage.launchimage并选择任何png的你想使用并点击“打开”。现在您可以使用[UIImage imageNamed:@"Default"];
答案 7 :(得分:1)
如果您需要确定设备,我会使用以下代码(它有点快速和肮脏,但它可以解决问题)
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");
}
}
答案 8 :(得分:1)
Matthew Burke的回答是正确的答案。下面是我正在使用的代码,用于iOS9 / Xcode7,为iOS7及更高版本构建应用程序,适用于iPhone和iPad,允许使用横向。
首先,详细说明一下: 在iOS8 / Xcode6中,如果您使用故事板启动屏幕文件,在应用启动时,应用程序将以正确的分辨率为您的设备创建该启动屏幕文件的2个图像(一个肖像,一个横向),您就可以获得来自文件路径的图像。 (我相信它存储在Library / LaunchImage文件夹中)。
然而,在iOS9 / XCode 7中,不再创建此图像(尽管快照文件夹中有一个快照,但它有一个不断变化的名称,所以如果你想在其他地方使用你的LaunchImage)您的代码,您必须使用启动图像源(最好通过资产目录,因为App Thinning)。现在,正如Matthew Burke所解释的那样,你无法通过这样做来达到那个形象:
let launchImage = UIImage(named: "LaunchImage")
即使资产目录中的图像名称是LaunchImage,Xcode / iOS9也不会让你。
幸运的是,您不必在资产目录中再次包含启动图像。幸运的是,如果您为所有设备制作应用程序,这意味着您的应用程序下载大小将增加20MB。
那么,如何获得那些发布图像呢?嗯,这是步骤:
然后,在您的代码中,您需要确定您的应用运行的设备,以及它是纵向还是横向,然后决定使用哪个图像。为了使这更容易,我使用了这个框架: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
}
答案 9 :(得分:1)
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"];
}
答案 10 :(得分:1)
以下是基于Daniel Witurna解决方案的修改代码。此代码段使用谓词从包图像列表中过滤启动图像名称。谓词可能会避免多个循环来从图像路径数组中过滤启动图像。
-(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; }
答案 11 :(得分:0)
创建Images.xcassets
后,只需将LaunchImage
重命名为Default
。
如果您支持iOS5和iOS6,这将节省很多麻烦。
“文件夹”/类别的实际名称将在构建时跟随资产。 马修伯克所说的其他一切都是真的;)
答案 12 :(得分:0)
在项目中创建一个新组,而不是由任何物理目录支持。直接从LaunchImage.launchimage
将您的启动图片导入该群组。瞧。
答案 13 :(得分:0)
基于Daniel的excellent answer的另一种更现代,更优雅的解决方案:
extension UIImage {
static var launchImage: UIImage? {
let pngs = Bundle.main.paths(forResourcesOfType: "png", inDirectory: nil)
return pngs
.filter({$0.contains("LaunchImage")})
.compactMap({UIImage(named: $0)})
.filter({$0.size == UIScreen.main.bounds.size})
.first
}
}
那样,您可以编写:
let myLaunchImage = UIImage.launchImage
答案 14 :(得分:-1)
由于“LaunchImage”资产实际上是一个自定义野兽......
我的建议是创建一个二级资产目录,其中包含图像副本(或您实际需要的子集)。
我称之为 FauxLaunchImage 。他们可以像你想要的那样访问它
[UIImage imageNamed:@"FauxLaunchImage"];