iOS 7 / Xcode 5: el dispositivo de acceso inicia imágenes mediante progtwigción

¿Hay alguna forma de utilizar las aplicaciones LaunchImage como fondo en una aplicación universal de iOS sin poner los mismos recursos de imágenes en varios lugares?

No pude acceder a los archivos de Images.xcassets en Images.xcassets , así que creé dos nuevos conjuntos de imágenes, “Background Portrait” y “Background Landscape” (ya que parece que no hay forma de poner imágenes de paisaje y retrato en el mismo conjunto) .

Si bien esta solución hace los trabajos, me gustaría incluir cada imagen en la aplicación dos veces. Esto también tiene un alto costo de mantenimiento.

Se agradece cualquier consejo sobre cómo acceder a LaunchImage para el dispositivo actual.

GCOLaunchImageTransition debe haber hecho el trabajo para iOS <7.

Puede usar las imágenes de inicio sin tener que incluirlas dos veces. La clave es que cuando utiliza un catálogo de activos, los nombres de archivo de las imágenes que se incluyen en el paquete de la aplicación están (en cierto modo) estandarizados y pueden no estar relacionados con los nombres que usted asignó a los archivos originales.

En particular, cuando utiliza el conjunto de imágenes LaunchImage, los archivos que terminan en el paquete de la aplicación tienen nombres como

Nota: en particular, no se denominan Default.png o cualquier variación de eso. Incluso si eso es lo que llamaste los archivos. Una vez que los haya soltado en uno de los pozos del catálogo de activos, saldrán por el otro extremo con un nombre estándar.

Entonces [UIImage imageNamed:@"Default"] no funcionará porque no hay tal archivo en el paquete de la aplicación. Sin embargo, [UIImage imageNamed:@"LaunchImage"] funcionará (suponiendo que hayas rellenado bien el iPhone Portrait 2x o el pre iOS7 iPhone Portrait 1x).

La documentación indica que el método imageNamed: en UIImage debe seleccionar automáticamente la versión correcta, pero creo que esto solo se aplica a los conjuntos de imágenes que no sean la imagen de inicio, al menos no lo he hecho funcionar correctamente ( podría simplemente no estoy haciendo algo bien ).

Por lo tanto, dependiendo de sus circunstancias exactas, es posible que deba realizar una pequeña prueba y error para obtener el nombre correcto del archivo. Cree y ejecute la aplicación en el simulador y luego siempre puede buscar en el subdirectorio apropiado de ~/Library/Application Support/iPhone Simulator para verificar cuáles son los nombres reales de archivo en el paquete de la aplicación.

Pero una vez más, el punto principal es que no es necesario incluir duplicados de los archivos de imagen y no es necesario realizar ningún ajuste en la fase de comstackción Copy Bundle Resources .

Puede copiar / pegar el siguiente código para cargar la imagen de inicio de su aplicación en tiempo de ejecución:

 // 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]]; 

La mayoría de las respuestas requieren crear un nombre de imagen dependiendo del tipo de dispositivo, escala, tamaño, etc. Pero como señaló Matthew Burke, cada imagen dentro del catálogo de imágenes de lanzamiento cambiará de nombre a “LaunchImage *” y por lo tanto podemos iterar a través de nuestro lanzamiento imágenes y encuentre la imagen apropiada (para el dispositivo actual). En Objective-C podría verse así:

 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; } } } 

(Tenga en cuenta que este código utiliza el método “containsString” introducido con iOS 8. Para versiones anteriores de iOS use “rangeOfString”)

A continuación se muestra el resultado cuando pruebo en iOS 7.0+, solo retrato:

 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 

Una versión Swift de la excelente respuesta de Daniel Witurna que no requiere verificación contra una lista de todos los tipos de dispositivos u orientaciones conocidos.

 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 } 

Una función concisa en Swift para obtener el nombre de la imagen de lanzamiento en tiempo de ejecución:

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

Info.plist en paquete contiene información de la imagen de inicio, incluido el nombre de la imagen de inicio.

C objective:

 - (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]; } 

Swift 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 } 

No sé si esto es lo que quieres decir con el acceso a través del código. Pero si selecciona su “proyecto-> objective-> fases de comstackción-> copie recursos del paquete”, haga clic en “+” y “agregar otro” navegue a Images.xcassets-> LaunchImage.launchimage y seleccione cualquier png que desee utilizar. y haz clic en “abrir”. Ahora puede usar la imagen como [UIImage imageNamed:@"Default"];

Si necesita determinar el dispositivo, uso el siguiente código (es un poco rápido y sucio, pero funciona)

 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"); } } 

La respuesta de Matthew Burke es la respuesta correcta. A continuación se muestra el código que estoy usando para que esto funcione para iOS9 / Xcode7, crear una aplicación para iOS7 y superior, para iPhone y iPad, paisaje permitido.

Primero, para elaborar un poco más: en iOS8 / Xcode6, si usabas un storyboard Launch Screen File, al inicio de la aplicación, la aplicación crearía 2 imágenes (un retrato, un paisaje) de ese archivo de pantalla de inicio con la resolución correcta para su dispositivo y usted pudo obtener esa imagen de la ruta del archivo. (Creo que fue almacenado en la carpeta Library / LaunchImage).

Sin embargo, en iOS9 / XCode 7 esta imagen ya no se crea (aunque se toma una instantánea en la carpeta de instantáneas, pero tiene un nombre no descriptivo que cambia todo el tiempo), así que si quieres usar tu LaunchImage en otro lugar de tu código, tendrá que utilizar un origen de imagen de inicio (a través del catálogo de activos preferiblemente, debido al adelgazamiento de la aplicación). Ahora, como Matthew Burke está explicando, no puedes llegar a esa imagen simplemente haciendo:

 let launchImage = UIImage(named: "LaunchImage") 

Aunque el nombre de la imagen en su catálogo de activos es LaunchImage, Xcode / iOS9 no le permitirá.

Afortunadamente, no tiene que volver a incluir sus imágenes de lanzamiento en su catálogo de activos. Estoy diciendo afortunadamente porque eso significaría un aumento de 20 MB del tamaño de la descarga de su aplicación si está haciendo una aplicación para todos los dispositivos.

Entonces, ¿cómo llegar a esas imágenes de lanzamiento que? Bueno, aquí están los pasos:

  1. Cree sus imágenes de lanzamiento y colóquelas en su catálogo de activos. El nombre de las imágenes no es importante.
  2. Asegúrese de que su archivo de pantalla de inicio (en la configuración general de su destino) esté vacío y elimine su aplicación de su dispositivo y simulador. (simplemente eliminar el nombre del archivo y volver a ejecutarlo no lo hará, primero tendrá que eliminar su aplicación)
  3. Ejecute su aplicación en el simulador y vaya a la carpeta ~ / Library / Application Support / iPhone Simulator y encuentre allí su aplicación. (Es un poco complicado ya que los nombres de las carpetas son indescriptivos.) Muestre el contenido del paquete para su archivo .app y verá varios archivos de imágenes que comienzan con “LaunchImage- …” En mi caso, había 9 imágenes ya que estoy creando una aplicación para iPhone y iPad para iOS 7 en adelante.
  4. Luego, en su código necesitará determinar en qué dispositivo se ejecuta su aplicación y si está en vertical u horizontal y luego decidir qué imagen usar. Para hacer esto un poco más fácil, utilicé este marco: https://github.com/InderKumarRathore/DeviceGuru . Tenga en cuenta que aún no incluía los últimos dispositivos (iPhone 6s y iPhone 6s plus) por lo que tendrá que agregar una línea en su archivo rápido para eso. Luego, coloque debajo del fragmento de código en el vc donde desea que aparezca su launchImage, y allí irá:

     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"]; } 

Aquí está el código modificado basado en la solución de Daniel Witurna. Este fragmento de código utiliza un predicado para filtrar el nombre de la imagen de inicio de la lista de imágenes del paquete. Predicate potencialmente evitará el número de bucles para filtrar la imagen de inicio de una matriz de rutas de imágenes.

 -(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; } 

Una vez que haya creado Images.xcassets , simplemente cambie el nombre de LaunchImage a Default .

Esto te ahorrará muchos problemas si soportas iOS5 e iOS6.

El nombre real de la “carpeta” / categoría seguirá en el activo en la comstackción. Todo lo demás es cierto lo que dijo Matthew Burke;)

Cree un nuevo grupo en su proyecto, no respaldado por ningún directorio físico. Importe en ese grupo sus imágenes de lanzamiento, directamente desde LaunchImage.launchimage . Voilá.

Dado que el activo “LaunchImage” es en realidad una bestia personalizada …

Mi sugerencia es crear un catálogo de activos secundario con duplicados de las imágenes (o el subconjunto que realmente necesita).

Yo llamo al mío FauxLaunchImage . Pueden acceder a él como quisieras

 [UIImage imageNamed:@"FauxLaunchImage"];