it-swarm.com.ru

iOS 7/Xcode 5: запуск устройства доступа к программным изображениям

Есть ли способ использовать приложения LaunchImage в качестве фона в универсальном приложении для iOS, не размещая одни и те же ресурсы изображений в нескольких местах?

Мне не удалось получить доступ к файлам LaunchImage в Images.xcassets, поэтому я создал два новых набора изображений «Фоновый портрет» и «Фоновый пейзаж» (поскольку, похоже, нет способа поместить альбомные и портретные изображения в один и тот же набор).

Хотя этот обходной путь делает свою работу, я бы не хотел включать каждое изображение в приложение дважды. Это также имеет высокую стоимость обслуживания.

Любой совет о том, как получить доступ к LaunchImage для текущего устройства приветствуется.

GCOLaunchImageTransition должен был выполнить работу для iOS <7.

41
Timm

Вы можете использовать образы запуска без необходимости включать их дважды. Ключевым моментом является то, что при использовании каталога ресурсов имена файлов изображений, включенных в комплект приложения, стандартизируются (в некотором роде) и могут не относиться к тому, что вы назвали исходными файлами.

В частности, когда вы используете набор изображений 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.

42
Matthew Burke

Вы можете скопировать/вставить следующий код, чтобы загрузить образ запуска вашего приложения во время выполнения:

// Load launch image
NSString *launchImageName;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
    if ([UIScreen mainScreen].bounds.size.height == 480) launchImageName = @"[email protected]"; // iPhone 4/4s, 3.5 inch screen
    if ([UIScreen mainScreen].bounds.size.height == 568) launchImageName = @"[email protected]"; // iPhone 5/5s, 4.0 inch screen
    if ([UIScreen mainScreen].bounds.size.height == 667) launchImageName = @"[email protected]"; // iPhone 6, 4.7 inch screen
    if ([UIScreen mainScreen].bounds.size.height == 736) launchImageName = @"[email protected]"; // 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 = @"[email protected]~ipad.png"; // Retina iPads
}
self.launchImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:launchImageName]];
55
John Erck

Большинство ответов требуют создания имени изображения в зависимости от типа устройства, масштаба, размера и т.д. Но, как отметил Мэтью Берк, каждое изображение в каталоге стартовых изображений будет переименовано в «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;
        }
    }
}

(Обратите внимание, что в этом коде используется метод containsString, представленный в iOS 8. Для предыдущих версий iOS используйте rangeOfString)

40
Daniel Witurna

Ниже приведен результат при тестировании в iOS 7.0+, только портретная ориентация:

3.5 inch screen: [email protected]
4.0 inch screen: [email protected]
4.7 inch screen: [email protected]
5.5 inch screen: [email protected]
iPad2          : LaunchImage-700-Portrait~ipad.png
Retina iPads   : [email protected]~ipad.png
10
ZYiOS

Swift-версия отличного answer от Daniel Witurna, которая не требует сверки со списком всех известных типов устройств или ориентаций.

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
}
9
Simo

Info.plist в комплекте содержит информацию об образе запуска, включая имя образа запуска.

Objective-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
}
4
Lavare

Краткая функция в Swift для получения имени образа запуска во время выполнения:

func launchImageName() -> String {
    switch (UI_USER_INTERFACE_IDIOM(), UIScreen.mainScreen().scale, UIScreen.mainScreen().bounds.size.height) {
        case (.Phone, _, 480): return "[email protected]"
        case (.Phone, _, 568): return "[email protected]"
        case (.Phone, _, 667): return "[email protected]"
        case (.Phone, _, 736): return "LaunchImage-800-Portrait-73[email protected]"
        case (.Pad, 1, _): return "LaunchImage-700-Portrait~ipad.png"
        case (.Pad, 2, _): return "[email protected]~ipad.png"
        default: return "LaunchImage"
    }
}
2
Jason Cabot

Ответ Мэтью Бёрка - правильный ответ. Ниже приведен код, который я использую для работы с iOS9/Xcode7, создания приложения для iOS7 и выше, для iPhone и iPad, допускается альбомная ориентация.

Для начала немного подробнее: В iOS8/Xcode6, если вы использовали файл экрана раскадровки Launch Screen File, при запуске приложения приложение должно было создать 2 изображения (один портрет, один пейзаж) из этого файла экрана запуска в правильное разрешение для вашего устройства, и вы смогли получить это изображение из пути к файлу. (Я считаю, что он был сохранен в папке Library/LaunchImage). 

Однако в iOS9/XCode 7 это изображение больше не создается (хотя снимок сделан в папке моментальных снимков, но у него неинформативное имя, которое постоянно меняется), поэтому, если вы хотите использовать LaunchImage где-то еще в вашем коде, вам придется использовать Launch Image Source (желательно через каталог ресурсов, из-за тонкости приложения). Теперь, как объясняет Мэтью Берк, вы не можете получить это изображение, просто выполнив:

let launchImage = UIImage(named: "LaunchImage")

Даже если имя изображения в вашем каталоге ресурсов - LaunchImage, Xcode/iOS9 не позволит вам.

К счастью, вам не нужно снова включать образы запуска в каталог активов. Я к счастью говорю, потому что это означало бы увеличение размера загрузки приложения на 20 МБ, если вы создаете приложение для всех устройств. 

Итак, как добраться до этих изображений запуска, чем? Ну, вот шаги:

  1. Создайте свои изображения запуска и поместите их в свой каталог ресурсов. Название картинки не важно.
  2. Убедитесь, что ваш файл экрана запуска (в общих настройках вашей цели) пуст и удалите приложение с устройства и симулятора. (простое удаление имени файла и повторный запуск не сделают этого, сначала вам придется удалить приложение)
  3. Запустите приложение в симуляторе, перейдите в папку ~/Library/Application Support/iPhone Simulator и найдите там свое приложение. (Это немного хлопотно, так как имена папок не являются описательными.) Покажите содержимое пакета для вашего .app-файла, и там вы увидите несколько файлов изображений, начинающихся с «LaunchImage- ...». В моем случае было 9 изображений как я делаю приложение для iPhone и iPad для iOS7 и выше.
  4. Затем в своем коде вам нужно определить, на каком устройстве работает ваше приложение и находится ли он в книжной или альбомной ориентации, а затем решить, какое изображение использовать. Чтобы сделать это немного проще, я использовал эту платформу: https://github.com/InderKumarRathore/DeviceGuru . Будьте осторожны, он еще не включал в себя последние устройства (iPhone 6s и iPhone 6s plus), поэтому вам придется добавить строку в его файл Swift для этого. Затем поместите ниже кусок кода в VC, где вы хотите, чтобы ваш launchImage и там вы идете:

    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 = "[email protected]"
        let HD40 = "[email protected]"
        let HD47 = "[email protected]"
        var HD55 = "[email protected]"
        var padHD = "[email protected]~ipad.png"
        var pad = "LaunchImage-700-Portrait~ipad.png"
    
        if UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft || UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeRight {
            HD55 = "[email protected]"
            padHD = "[email protected]~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
    }
    
1
guido

Вот модифицированный код, основанный на решении Daniel Witurna. Этот фрагмент кода использует предикат для фильтрации имени образа запуска из списка изображений комплекта. Predicate потенциально позволит избежать количества циклов фильтрации фильтра запуска из массива путей изображения.

-(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; }
1
Saikiran K

Я не знаю, имеет ли это в виду доступ через код. Но если вы выберете свой «проект-> целевой-> этапы сборки-> скопировать ресурсы комплекта», нажмите «+» и «добавьте другие», перейдите к своему Images.xcassets-> LaunchImage.launchimage и выберите любой png, который вы хотите использовать и нажмите «открыть». Теперь вы можете использовать изображение как [UIImage imageNamed:@"Default"];

1
Peter Segerblom
 if (IS_IPHONE_4_OR_LESS) {
    self.imageView.image = [UIImage imageNamed:@"[email protected]"];
}
else if (IS_IPHONE_5){
     self.imageView.image = [UIImage imageNamed:@"[email protected]"];
}
else if (IS_IPHONE_6){
     self.imageView.image = [UIImage imageNamed:@"[email protected]"];
}
else if (IS_IPHONE_6P){
      self.imageView.image = [UIImage imageNamed:@"[email protected]"];
}
1
shweta sharma

Если вам нужно определить устройство, я использую следующий код (он немного быстрый и грязный, но делает свое дело)

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

После того, как вы создали Images.xcassets, просто переименуйте LaunchImage в Default.

Это избавит вас от многих проблем, если вы поддерживаете iOS5 и iOS6.

Фактическое имя «папка»/категория будет следовать в активе при сборке .... Все остальное верно, что сказал Мэтью Берк;)

0
Danoli3

Создайте новую группу в своем проекте, не опираясь на какой-либо физический каталог. Импортируйте в эту группу ваши изображения запуска, прямо из LaunchImage.launchimage. Вуаля.

0
QED